diff --git a/9781430248187.jpg b/9781430248187.jpg
new file mode 100644
index 0000000..cd06485
Binary files /dev/null and b/9781430248187.jpg differ
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..1b49133
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,27 @@
+Freeware License, some rights reserved
+
+Copyright (c) 2013 Carlo Scarioni
+
+Permission is hereby granted, free of charge, to anyone obtaining a copy
+of this software and associated documentation files (the "Software"),
+to work with the Software within the limits of freeware distribution and fair use.
+This includes the rights to use, copy, and modify the Software for personal use.
+Users are also allowed and encouraged to submit corrections and modifications
+to the Software for the benefit of other users.
+
+It is not allowed to reuse, modify, or redistribute the Software for
+commercial use in any way, or for a users educational materials such as books
+or blog articles without prior permission from the copyright holder.
+
+The above copyright notice and this permission notice need to be included
+in all copies or substantial portions of the software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a4dae7b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+#Apress Source Code
+
+This repository accompanies [*Pro Spring Security*](http://www.apress.com/9781430248187) by Carlo Scarioni (Apress, 2013).
+
+![Cover image](9781430248187.jpg)
+
+Download the files as a zip using the green button, or clone the repository to your machine using Git.
+
+##Releases
+
+Release v1.0 corresponds to the code in the published book, without corrections or updates.
+
+##Contributions
+
+See the file Contributing.md for more information on how you can contribute to this repository.
diff --git a/ch01/ch01/.DS_Store b/ch01/ch01/.DS_Store
new file mode 100644
index 0000000..e68ff72
Binary files /dev/null and b/ch01/ch01/.DS_Store differ
diff --git a/ch01/ch01/pss01-fromscratch/.classpath b/ch01/ch01/pss01-fromscratch/.classpath
new file mode 100644
index 0000000..ae98bae
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.classpath
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch01/ch01/pss01-fromscratch/.project b/ch01/ch01/pss01-fromscratch/.project
new file mode 100644
index 0000000..4205126
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.project
@@ -0,0 +1,42 @@
+
+
+ pss01-fromscratch
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch01/ch01/pss01-fromscratch/.settings/.jsdtscope b/ch01/ch01/pss01-fromscratch/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.jdt.core.prefs b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.m2e.core.prefs b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.common.component b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..fcb1bfb
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch01/ch01/pss01-fromscratch/pom.xml b/ch01/ch01/pss01-fromscratch/pom.xml
new file mode 100644
index 0000000..6ab89b8
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/pom.xml
@@ -0,0 +1,55 @@
+
+ 4.0.0
+ com.apress.pss
+ pss01
+ war
+ 1.0-SNAPSHOT
+ pss01 Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+ pss01
+
+
diff --git a/ch01/ch01/pss01-fromscratch/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch01/ch01/pss01-fromscratch/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..af4f12b
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns = { "/hello" })
+public class HelloWorldServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch01/ch01/pss01-fromscratch/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch01/ch01/pss01-fromscratch/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..aaf02c5
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch01/ch01/pss01-fromscratch/src/main/webapp/WEB-INF/web.xml b/ch01/ch01/pss01-fromscratch/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..7878db1
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,25 @@
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
diff --git a/ch01/ch01/pss01-fromscratch/src/main/webapp/index.jsp b/ch01/ch01/pss01-fromscratch/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch01/ch01/pss01-fromscratch/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch01/ch01/pss01/.DS_Store b/ch01/ch01/pss01/.DS_Store
new file mode 100644
index 0000000..d432ed5
Binary files /dev/null and b/ch01/ch01/pss01/.DS_Store differ
diff --git a/ch01/ch01/pss01/.classpath b/ch01/ch01/pss01/.classpath
new file mode 100644
index 0000000..042eef3
--- /dev/null
+++ b/ch01/ch01/pss01/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch01/ch01/pss01/.project b/ch01/ch01/pss01/.project
new file mode 100644
index 0000000..d7fb34b
--- /dev/null
+++ b/ch01/ch01/pss01/.project
@@ -0,0 +1,42 @@
+
+
+ pss01
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch01/ch01/pss01/.settings/.jsdtscope b/ch01/ch01/pss01/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch01/ch01/pss01/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch01/ch01/pss01/.settings/org.eclipse.jdt.core.prefs b/ch01/ch01/pss01/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch01/ch01/pss01/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch01/ch01/pss01/.settings/org.eclipse.m2e.core.prefs b/ch01/ch01/pss01/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch01/ch01/pss01/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch01/ch01/pss01/.settings/org.eclipse.wst.common.component b/ch01/ch01/pss01/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..0f0acc4
--- /dev/null
+++ b/ch01/ch01/pss01/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch01/ch01/pss01/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch01/ch01/pss01/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..ef27789
--- /dev/null
+++ b/ch01/ch01/pss01/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch01/ch01/pss01/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch01/ch01/pss01/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch01/ch01/pss01/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch01/ch01/pss01/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch01/ch01/pss01/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch01/ch01/pss01/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch01/ch01/pss01/pom.xml b/ch01/ch01/pss01/pom.xml
new file mode 100644
index 0000000..c6b807b
--- /dev/null
+++ b/ch01/ch01/pss01/pom.xml
@@ -0,0 +1,67 @@
+
+ 4.0.0
+ com.apress.pss
+ pss01
+ war
+ 1.0-SNAPSHOT
+ pss01 Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch01/ch01/pss01/src/.DS_Store b/ch01/ch01/pss01/src/.DS_Store
new file mode 100644
index 0000000..48bf7fa
Binary files /dev/null and b/ch01/ch01/pss01/src/.DS_Store differ
diff --git a/ch01/ch01/pss01/src/main/.DS_Store b/ch01/ch01/pss01/src/main/.DS_Store
new file mode 100644
index 0000000..9cf25de
Binary files /dev/null and b/ch01/ch01/pss01/src/main/.DS_Store differ
diff --git a/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessObject.java b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessObject.java
new file mode 100644
index 0000000..c79a0a8
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessObject.java
@@ -0,0 +1,9 @@
+package com.apress.pss.discard;
+
+public class BusinessObject implements BusinessThing{
+
+ public void doBusinessThing() {
+ //Some business stuff
+ }
+
+}
diff --git a/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessObjectTransactionalDecorator.java b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessObjectTransactionalDecorator.java
new file mode 100644
index 0000000..4da4df7
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessObjectTransactionalDecorator.java
@@ -0,0 +1,15 @@
+package com.apress.pss.discard;
+
+public class BusinessObjectTransactionalDecorator implements BusinessThing {
+ private BusinessThing component;
+
+ public BusinessObjectTransactionalDecorator(BusinessThing component){
+ this.component = component;
+ }
+ public void doBusinessThing() {
+ //some start transaction code
+ component.doBusinessThing();
+ //some commit transaction code
+ }
+
+}
diff --git a/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessThing.java b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessThing.java
new file mode 100644
index 0000000..2157b4b
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/BusinessThing.java
@@ -0,0 +1,5 @@
+package com.apress.pss.discard;
+
+public interface BusinessThing {
+ void doBusinessThing();
+}
diff --git a/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/DiObject.java b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/DiObject.java
new file mode 100644
index 0000000..b6fc55b
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/DiObject.java
@@ -0,0 +1,13 @@
+package com.apress.pss.discard;
+
+public class DiObject {
+ private Helper helper;
+
+ public DiObject(Helper helper) {
+ this.helper = helper;
+ }
+
+ public void doStuffWithHelp(){
+ helper.help();
+ }
+}
diff --git a/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/Helper.java b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/Helper.java
new file mode 100644
index 0000000..9df501a
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/Helper.java
@@ -0,0 +1,5 @@
+package com.apress.pss.discard;
+
+public interface Helper {
+ void help();
+}
diff --git a/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/HelperImpl.java b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/HelperImpl.java
new file mode 100644
index 0000000..32725f7
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/HelperImpl.java
@@ -0,0 +1,8 @@
+package com.apress.pss.discard;
+
+public class HelperImpl implements Helper {
+
+ public void help() {
+ System.out.println("Helping");
+ }
+}
diff --git a/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/NonDiObject.java b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/NonDiObject.java
new file mode 100644
index 0000000..29f7d4d
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/java/com/apress/pss/discard/NonDiObject.java
@@ -0,0 +1,13 @@
+package com.apress.pss.discard;
+
+public class NonDiObject {
+ private Helper helper;
+
+ public NonDiObject(){
+ helper = new HelperImpl();
+ }
+
+ public void doStuffWithHelp(){
+ helper.help();
+ }
+}
diff --git a/ch01/ch01/pss01/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch01/ch01/pss01/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch01/ch01/pss01/src/main/webapp/.DS_Store b/ch01/ch01/pss01/src/main/webapp/.DS_Store
new file mode 100644
index 0000000..160729c
Binary files /dev/null and b/ch01/ch01/pss01/src/main/webapp/.DS_Store differ
diff --git a/ch01/ch01/pss01/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch01/ch01/pss01/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..b237dea
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch01/ch01/pss01/src/main/webapp/WEB-INF/web.xml b/ch01/ch01/pss01/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch01/ch01/pss01/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch04/ch05/.DS_Store b/ch04/ch05/.DS_Store
new file mode 100644
index 0000000..29f133d
Binary files /dev/null and b/ch04/ch05/.DS_Store differ
diff --git a/ch04/ch05/pss01/terrormovies/.classpath b/ch04/ch05/pss01/terrormovies/.classpath
new file mode 100644
index 0000000..8d1b877
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.classpath
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch04/ch05/pss01/terrormovies/.project b/ch04/ch05/pss01/terrormovies/.project
new file mode 100644
index 0000000..635a5c8
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.project
@@ -0,0 +1,48 @@
+
+
+ terrormovies
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch04/ch05/pss01/terrormovies/.settings/.jsdtscope b/ch04/ch05/pss01/terrormovies/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.jdt.core.prefs b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..443e085
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.m2e.core.prefs b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.common.component b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..43127a5
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch04/ch05/pss01/terrormovies/pom.xml b/ch04/ch05/pss01/terrormovies/pom.xml
new file mode 100644
index 0000000..811bbaf
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/pom.xml
@@ -0,0 +1,123 @@
+
+ 4.0.0
+ com.apress.pss
+ terrormovies
+ war
+ 0.0.1-SNAPSHOT
+ terrormovies Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.0.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.0.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.0.RELEASE
+
+
+ org.springframework.security
+ spring-security-taglibs
+ 3.1.0.RELEASE
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ javax.servlet.jsp
+ jsp-api
+ 2.1
+
+
+ javax.servlet
+ jstl
+ 1.2
+
+
+
+
+
+
+ org.codehaus.mojo
+ keytool-maven-plugin
+
+
+ generate-resources
+ clean
+
+ clean
+
+
+
+ generate-resources
+ genkey
+
+ genkey
+
+
+
+
+ ${project.build.directory}/jetty-ssl.keystore
+ cn=apress.pss
+ jetty8
+ jetty8
+ jetty6
+ RSA
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+ 8443
+ 60000
+ ${project.build.directory}/jetty-ssl.keystore
+ jetty8
+ jetty8
+
+
+
+
+
+ terrormovies
+
+
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java
new file mode 100644
index 0000000..1be99a0
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java
@@ -0,0 +1,31 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.apress.pss.terrormovies.model.User;
+
+@Controller
+@RequestMapping("/admin")
+public class AdminController {
+
+ @RequestMapping(method = RequestMethod.POST, value = "/movies")
+ @ResponseBody
+ public String createMovie(@RequestBody String movie) {
+ System.out.println("Adding movie!! "+movie);
+ return "created";
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/movies")
+ @ResponseBody
+ public String createMovie() {
+ User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ System.out.println("returned movie!");
+ return "User "+user.getLastname()+" is accessing movie x";
+ }
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java
new file mode 100644
index 0000000..0929f11
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java
@@ -0,0 +1,16 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+
+@Controller
+@RequestMapping("")
+public class LoginController {
+ @RequestMapping(method = RequestMethod.GET, value = "/custom_login")
+ public String showLogin(){
+ return "login";
+ }
+
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java
new file mode 100644
index 0000000..f828471
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java
@@ -0,0 +1,46 @@
+package com.apress.pss.terrormovies.controller;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.apress.pss.terrormovies.model.Movie;
+
+@Controller
+@RequestMapping("/movies")
+public class MovieController {
+
+ private Map likedMovies;
+
+ public MovieController(){
+ likedMovies = new HashMap();
+ likedMovies.put(1, new String[]{"Die Hard", "Lethal Weapon"});
+ }
+ @RequestMapping(method = RequestMethod.GET, value = "/member/{id}")
+ @ResponseBody
+ public String getMoviesForMember(@PathVariable int id) {
+ StringBuilder builder = new StringBuilder();
+ for(String movie:likedMovies.get(id)){
+ builder.append(movie);
+ }
+ return builder.toString();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/")
+ public ModelAndView getAllMovies() {
+ ModelAndView mv = new ModelAndView("movies");
+ List movies = new ArrayList();
+ movies.add(new Movie("Die hard", "25000000"));
+ movies.add(new Movie("Lethatl Weapon", "30000000"));
+ mv.addObject("movies", movies);
+ return mv;
+ }
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/model/Movie.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/model/Movie.java
new file mode 100644
index 0000000..550267d
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/model/Movie.java
@@ -0,0 +1,22 @@
+package com.apress.pss.terrormovies.model;
+
+public class Movie {
+ private String name;
+ private String budget;
+
+
+ public Movie(String name, String budget) {
+ super();
+ this.name = name;
+ this.budget = budget;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getBudget() {
+ return budget;
+ }
+
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/model/User.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/model/User.java
new file mode 100644
index 0000000..dfe0396
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/model/User.java
@@ -0,0 +1,34 @@
+package com.apress.pss.terrormovies.model;
+
+import java.util.Collection;
+
+import org.springframework.security.core.GrantedAuthority;
+
+public class User extends org.springframework.security.core.userdetails.User{
+
+ private String lastname;
+ private int age;
+
+ public User(String username, String password, boolean enabled,
+ boolean accountNonExpired, boolean credentialsNonExpired,
+ boolean accountNonLocked,
+ Collection extends GrantedAuthority> authorities, String lastname, int age) {
+ super(username, password, enabled, accountNonExpired, credentialsNonExpired,
+ accountNonLocked, authorities);
+ this.lastname = lastname;
+ this.age=age;
+ }
+
+ public User(String username, String password, Collection extends GrantedAuthority> authorities, String lastname, int age) {
+ this(username, password, true, true, true, true, authorities, lastname,age);
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java
new file mode 100644
index 0000000..9f12e99
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java
@@ -0,0 +1,18 @@
+package com.apress.pss.terrormovies.security;
+
+import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
+import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.FilterInvocation;
+
+public class CustomWebSecurityExpressionHandler extends AbstractSecurityExpressionHandler {
+
+ @Override
+ protected SecurityExpressionRoot createSecurityExpressionRoot(
+ Authentication authentication, FilterInvocation invocation) {
+ CustomWebSecurityExpressionRoot root = new CustomWebSecurityExpressionRoot(authentication, invocation);
+ root.setPermissionEvaluator(getPermissionEvaluator());
+ return root;
+ }
+
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java
new file mode 100644
index 0000000..c305cab
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java
@@ -0,0 +1,20 @@
+package com.apress.pss.terrormovies.security;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.expression.WebSecurityExpressionRoot;
+
+import com.apress.pss.terrormovies.model.User;
+
+public class CustomWebSecurityExpressionRoot extends WebSecurityExpressionRoot{
+
+ public CustomWebSecurityExpressionRoot(Authentication a, FilterInvocation fi) {
+ super(a, fi);
+ }
+
+ public boolean isOver18(){
+ User user = (User)this.getPrincipal();
+ return user.getAge() >= 18;
+ }
+
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java
new file mode 100644
index 0000000..f725647
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java
@@ -0,0 +1,21 @@
+package com.apress.pss.terrormovies.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+
+public class ServerErrorFailureHandler implements AuthenticationFailureHandler{
+
+ public void onAuthenticationFailure(HttpServletRequest request,
+ HttpServletResponse response, AuthenticationException exception)
+ throws IOException, ServletException {
+ response.sendError(500);
+
+ }
+
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java
new file mode 100644
index 0000000..54189e6
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java
@@ -0,0 +1,35 @@
+package com.apress.pss.terrormovies.spring;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+import com.apress.pss.terrormovies.model.User;
+
+public class CustomInMemoryUserDetailsManager implements UserDetailsService {
+
+ private Map users = new HashMap();
+
+ public CustomInMemoryUserDetailsManager(Collection users) {
+ for (User user : users) {
+ this.users.put(user.getUsername().toLowerCase(), user);
+ }
+ }
+
+ public UserDetails loadUserByUsername(String username)
+ throws UsernameNotFoundException {
+ User user = users.get(username.toLowerCase());
+
+ if (user == null) {
+ throw new UsernameNotFoundException(username);
+ }
+ User userNew = new User(user.getUsername(), user.getPassword(), user.getAuthorities(), user.getLastname(), user.getAge());
+
+ return userNew;
+ }
+
+}
diff --git a/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..747cc3f
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/terrormovies-servlet.xml b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/terrormovies-servlet.xml
new file mode 100644
index 0000000..0d36596
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/terrormovies-servlet.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/views/login.jsp b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/views/login.jsp
new file mode 100644
index 0000000..ebb817a
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/views/login.jsp
@@ -0,0 +1,21 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+
+
+
+
+Terror movies
+
+
+ <% if(request.getParameter("error") != null){
+ out.println("ERROR LOGIN");
+ }
+ %>
+
+
+
\ No newline at end of file
diff --git a/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/views/movies.jsp b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/views/movies.jsp
new file mode 100644
index 0000000..f3fb673
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/views/movies.jsp
@@ -0,0 +1,26 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib prefix="security"
+ uri="http://www.springframework.org/security/tags"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+
+Terror movies
+
+
+ Mr
+
+
+
+ ${movie.name}
+
+
+ ${movie.budget}
+
+
+
+ You are a very appreciated VIP user
+
+
+
\ No newline at end of file
diff --git a/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/web.xml b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..b66f518
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,39 @@
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ terrormovies
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ terrormovies
+ /
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
+
+
diff --git a/ch04/ch05/pss01/terrormovies/src/main/webapp/index.jsp b/ch04/ch05/pss01/terrormovies/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch04/ch05/pss01/terrormovies/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch04/ch05/terrormovies/.classpath b/ch04/ch05/terrormovies/.classpath
new file mode 100644
index 0000000..ae98bae
--- /dev/null
+++ b/ch04/ch05/terrormovies/.classpath
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch04/ch05/terrormovies/.project b/ch04/ch05/terrormovies/.project
new file mode 100644
index 0000000..6b06ba0
--- /dev/null
+++ b/ch04/ch05/terrormovies/.project
@@ -0,0 +1,42 @@
+
+
+ terrormovies-WEB-FROM-SCRATCH
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch04/ch05/terrormovies/.settings/.jsdtscope b/ch04/ch05/terrormovies/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch04/ch05/terrormovies/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch04/ch05/terrormovies/.settings/org.eclipse.jdt.core.prefs b/ch04/ch05/terrormovies/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch04/ch05/terrormovies/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch04/ch05/terrormovies/.settings/org.eclipse.m2e.core.prefs b/ch04/ch05/terrormovies/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch04/ch05/terrormovies/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch04/ch05/terrormovies/.settings/org.eclipse.wst.common.component b/ch04/ch05/terrormovies/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..9865b5a
--- /dev/null
+++ b/ch04/ch05/terrormovies/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch04/ch05/terrormovies/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch04/ch05/terrormovies/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch04/ch05/terrormovies/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch04/ch05/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch04/ch05/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch04/ch05/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch04/ch05/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch04/ch05/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch04/ch05/terrormovies/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch04/ch05/terrormovies/pom.xml b/ch04/ch05/terrormovies/pom.xml
new file mode 100644
index 0000000..39dace0
--- /dev/null
+++ b/ch04/ch05/terrormovies/pom.xml
@@ -0,0 +1,112 @@
+
+ 4.0.0
+ com.apress.pss
+ terrormovies
+ war
+ 0.0.1-SNAPSHOT
+ terrormovies Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ org.springframework
+ spring-web
+ 3.0.7.RELEASE
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.7.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+
+
+
+ org.codehaus.mojo
+ keytool-maven-plugin
+
+
+ generate-resources
+ clean
+
+ clean
+
+
+
+ generate-resources
+ genkey
+
+ genkey
+
+
+
+
+ ${project.build.directory}/jetty-ssl.keystore
+ cn=apress.pss
+ jetty8
+ jetty8
+ jetty6
+ RSA
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+ 8443
+ 60000
+ ${project.build.directory}/jetty-ssl.keystore
+ jetty8
+ jetty8
+
+
+
+
+
+
+ terrormovies
+
+
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java
new file mode 100644
index 0000000..0e1dc9c
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java
@@ -0,0 +1,31 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.apress.pss.terrormovies.model.User;
+
+@Controller
+@RequestMapping("/admin")
+public class AdminController {
+
+ @RequestMapping(method = RequestMethod.POST, value = "/movies")
+ @ResponseBody
+ public String createMovie(@RequestBody String movie) {
+ System.out.println("Adding movie!! "+movie);
+ return "created";
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/movies")
+ @ResponseBody
+ public String createMovie() {
+ User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ System.out.println("returned movie!");
+ return "User "+user.getLastname()+" is accessing movie x";
+ }
+}
+
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java
new file mode 100644
index 0000000..6805bea
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java
@@ -0,0 +1,15 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@Controller
+@RequestMapping("")
+public class LoginController {
+ @RequestMapping(method = RequestMethod.GET, value = "/custom_login")
+ public String showLogin(){
+ return "login";
+ }
+
+}
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java
new file mode 100644
index 0000000..c38c93c
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java
@@ -0,0 +1,31 @@
+package com.apress.pss.terrormovies.controller;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping("/movies")
+public class MovieController {
+
+ private Map likedMovies;
+
+ public MovieController(){
+ likedMovies = new HashMap();
+ likedMovies.put(1, new String[]{"Die Hard", "Lethal Weapon"});
+ }
+ @RequestMapping(method = RequestMethod.GET, value = "/member/{id}")
+ @ResponseBody
+ public String getMoviesForMember(@PathVariable int id) {
+ StringBuilder builder = new StringBuilder();
+ for(String movie:likedMovies.get(id)){
+ builder.append(movie);
+ }
+ return builder.toString();
+ }
+}
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/model/Movie.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/model/Movie.java
new file mode 100644
index 0000000..550267d
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/model/Movie.java
@@ -0,0 +1,22 @@
+package com.apress.pss.terrormovies.model;
+
+public class Movie {
+ private String name;
+ private String budget;
+
+
+ public Movie(String name, String budget) {
+ super();
+ this.name = name;
+ this.budget = budget;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getBudget() {
+ return budget;
+ }
+
+}
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/model/User.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/model/User.java
new file mode 100644
index 0000000..328efe9
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/model/User.java
@@ -0,0 +1,34 @@
+package com.apress.pss.terrormovies.model;
+import java.util.Collection;
+
+import org.springframework.security.core.GrantedAuthority;
+
+public class User extends org.springframework.security.core.userdetails.User{
+
+ private String lastname;
+ private int age;
+
+ public User(String username, String password, boolean enabled,
+ boolean accountNonExpired, boolean credentialsNonExpired,
+ boolean accountNonLocked,
+ Collection extends GrantedAuthority> authorities, String lastname, int age) {
+ super(username, password, enabled, accountNonExpired, credentialsNonExpired,
+ accountNonLocked, authorities);
+ this.lastname = lastname;
+ this.age=age;
+ }
+
+ public User(String username, String password, Collection extends GrantedAuthority> authorities, String lastname, int age) {
+ this(username, password, true, true, true, true, authorities, lastname,age);
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+}
+
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java
new file mode 100644
index 0000000..1af20e1
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java
@@ -0,0 +1,20 @@
+package com.apress.pss.terrormovies.security;
+
+import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
+import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.FilterInvocation;
+
+public class CustomWebSecurityExpressionHandler extends AbstractSecurityExpressionHandler {
+
+ @Override
+ protected SecurityExpressionRoot createSecurityExpressionRoot(
+ Authentication authentication, FilterInvocation invocation) {
+ CustomWebSecurityExpressionRoot root = new CustomWebSecurityExpressionRoot(authentication, invocation);
+ root.setPermissionEvaluator(getPermissionEvaluator());
+ root.setTrustResolver(new AuthenticationTrustResolverImpl());
+ return root;
+ }
+
+}
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java
new file mode 100644
index 0000000..69c6150
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java
@@ -0,0 +1,19 @@
+package com.apress.pss.terrormovies.security;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.expression.WebSecurityExpressionRoot;
+
+import com.apress.pss.terrormovies.model.User;
+
+public class CustomWebSecurityExpressionRoot extends WebSecurityExpressionRoot{
+
+ public CustomWebSecurityExpressionRoot(Authentication a, FilterInvocation fi) {
+ super(a, fi);
+ }
+
+ public boolean isOver18(){
+ User user = (User)this.getPrincipal();
+ return user.getAge() > 18;
+ }
+
+}
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java
new file mode 100644
index 0000000..5ca9a03
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java
@@ -0,0 +1,20 @@
+package com.apress.pss.terrormovies.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+
+public class ServerErrorFailureHandler implements AuthenticationFailureHandler{
+
+ public void onAuthenticationFailure(HttpServletRequest request,
+ HttpServletResponse response, AuthenticationException exception)
+ throws IOException, ServletException {
+ response.sendError(500);
+
+ }
+}
diff --git a/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java
new file mode 100644
index 0000000..0ed948f
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java
@@ -0,0 +1,35 @@
+package com.apress.pss.terrormovies.spring;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+import com.apress.pss.terrormovies.model.User;
+
+public class CustomInMemoryUserDetailsManager implements UserDetailsService {
+
+ private Map users = new HashMap();
+
+ public CustomInMemoryUserDetailsManager(Collection users) {
+ for (User user : users) {
+ this.users.put(user.getUsername().toLowerCase(), user);
+ }
+ }
+
+ public UserDetails loadUserByUsername(String username)
+ throws UsernameNotFoundException {
+ User user = users.get(username.toLowerCase());
+
+ if (user == null) {
+ throw new UsernameNotFoundException(username);
+ }
+ User userNew = new User(user.getUsername(), user.getPassword(), user.getAuthorities(), user.getLastname(),user.getAge());
+
+ return userNew;
+ }
+
+}
diff --git a/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..4d5d6f3
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ROLE_ADMIN > ROLE_USER
+ ROLE_USER > ROLE_GUEST
+
+
+
+
+
+
diff --git a/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/terrormovies-servlet.xml b/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/terrormovies-servlet.xml
new file mode 100644
index 0000000..6fe051d
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/terrormovies-servlet.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/views/login.jsp b/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/views/login.jsp
new file mode 100644
index 0000000..e3a3249
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/views/login.jsp
@@ -0,0 +1,22 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+
+
+
+
+Terror movies
+
+
+<% if(request.getParameter("error") != null){
+ out.println("ERROR LOGIN");
+ }
+%>
+
+
+
+
diff --git a/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/web.xml b/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..5eaead2
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,40 @@
+
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+
+ springSecurityFilterChain
+ /*
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+ terrormovies
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ terrormovies
+ /
+
+
+
diff --git a/ch04/ch05/terrormovies/src/main/webapp/index.jsp b/ch04/ch05/terrormovies/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch04/ch05/terrormovies/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch05/ch06/aspectj-project/.classpath b/ch05/ch06/aspectj-project/.classpath
new file mode 100644
index 0000000..ae98bae
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.classpath
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch05/ch06/aspectj-project/.project b/ch05/ch06/aspectj-project/.project
new file mode 100644
index 0000000..ea5e634
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.project
@@ -0,0 +1,42 @@
+
+
+ aspectj-project
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch05/ch06/aspectj-project/.settings/.jsdtscope b/ch05/ch06/aspectj-project/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch05/ch06/aspectj-project/.settings/org.eclipse.jdt.core.prefs b/ch05/ch06/aspectj-project/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch05/ch06/aspectj-project/.settings/org.eclipse.m2e.core.prefs b/ch05/ch06/aspectj-project/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.common.component b/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..d4b5edd
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch05/ch06/aspectj-project/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch05/ch06/aspectj-project/ajcore.20121210.235412.326.txt b/ch05/ch06/aspectj-project/ajcore.20121210.235412.326.txt
new file mode 100644
index 0000000..995f007
--- /dev/null
+++ b/ch05/ch06/aspectj-project/ajcore.20121210.235412.326.txt
@@ -0,0 +1,151 @@
+---- AspectJ Properties ---
+AspectJ Compiler 1.6.4 built on Monday Apr 20, 2009 at 16:48:12 GMT
+---- Dump Properties ---
+Dump file: ajcore.20121210.235412.326.txt
+Dump reason: java.lang.NoSuchMethodError
+Dump on exception: true
+Dump at exit condition: abort
+---- Exception Information ---
+java.lang.NoSuchMethodError: org.aspectj.weaver.bcel.BcelWorld.setTiming(ZZ)V
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.initBcelWorld(AjBuildManager.java:831)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:245)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:181)
+ at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112)
+ at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
+ at org.aspectj.tools.ajc.Main.run(Main.java:371)
+ at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
+ at org.codehaus.mojo.aspectj.AbstractAjcCompiler.execute(AbstractAjcCompiler.java:405)
+ at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
+ at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
+ at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
+ at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
+ at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
+ at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:601)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
+---- System Properties ---
+java.runtime.name=Java(TM) SE Runtime Environment
+sun.boot.library.path=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib
+java.vm.version=23.1-b03
+user.country.format=GB
+gopherProxySet=false
+java.vm.vendor=Oracle Corporation
+java.vendor.url=http://java.oracle.com/
+guice.disable.misplaced.annotation.check=true
+path.separator=:
+java.vm.name=Java HotSpot(TM) 64-Bit Server VM
+file.encoding.pkg=sun.io
+user.country=US
+sun.java.launcher=SUN_STANDARD
+sun.os.patch.level=unknown
+java.vm.specification.name=Java Virtual Machine Specification
+user.dir=/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project
+java.runtime.version=1.7.0_05-b05
+java.awt.graphicsenv=sun.awt.CGraphicsEnvironment
+java.endorsed.dirs=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/endorsed
+os.arch=x86_64
+java.io.tmpdir=/var/folders/fn/1lyy5y556l11ghf7sc4tvvrw0000gn/T/
+line.separator=
+
+java.vm.specification.vendor=Oracle Corporation
+os.name=Mac OS X
+classworlds.conf=/usr/share/maven/bin/m2.conf
+sun.jnu.encoding=UTF-8
+java.library.path=/Users/cscarioni/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
+java.specification.name=Java Platform API Specification
+java.class.version=51.0
+sun.management.compiler=HotSpot 64-Bit Tiered Compilers
+os.version=10.7.5
+http.nonProxyHosts=local|*.local|169.254/16|*.169.254/16
+user.home=/Users/cscarioni
+user.timezone=Europe/London
+java.awt.printerjob=sun.lwawt.macosx.CPrinterJob
+file.encoding=UTF-8
+java.specification.version=1.7
+java.class.path=/usr/share/maven/boot/plexus-classworlds-2.4.jar
+user.name=cscarioni
+java.vm.specification.version=1.7
+sun.java.command=org.codehaus.plexus.classworlds.launcher.Launcher aspectj:compile
+java.home=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre
+sun.arch.data.model=64
+user.language=en
+java.specification.vendor=Oracle Corporation
+awt.toolkit=sun.lwawt.macosx.LWCToolkit
+java.vm.info=mixed mode
+java.version=1.7.0_05
+java.ext.dirs=/Users/cscarioni/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
+sun.boot.class.path=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/JObjC.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes
+java.vendor=Oracle Corporation
+maven.home=/usr/share/maven
+file.separator=/
+java.vendor.url.bug=http://bugreport.sun.com/bugreport/
+sun.io.unicode.encoding=UnicodeBig
+sun.cpu.endian=little
+socksNonProxyHosts=local|*.local|169.254/16|*.169.254/16
+ftp.nonProxyHosts=local|*.local|169.254/16|*.169.254/16
+sun.cpu.isalist=
+---- Command Line ---
+-classpath
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+-d
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/Service.java
+---- Full Classpath ---
+Empty
+---- Compiler Messages ---
+warning couldn't find aspectjrt.jar on classpath, checked: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/JObjC.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/System/Library/Java/Extensions/AppleScriptEngine.jar:/System/Library/Java/Extensions/dns_sd.jar:/System/Library/Java/Extensions/j3daudio.jar:/System/Library/Java/Extensions/j3dcore.jar:/System/Library/Java/Extensions/j3dutils.jar:/System/Library/Java/Extensions/jai_codec.jar:/System/Library/Java/Extensions/jai_core.jar:/System/Library/Java/Extensions/mlibwrapper_jai.jar:/System/Library/Java/Extensions/MRJToolkit.jar:/System/Library/Java/Extensions/QTJava.zip:/System/Library/Java/Extensions/vecmath.jar:/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+info directory classpath entry does not exist: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar
+info zipfile classpath entry does not exist: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes
+abort ABORT -- (NoSuchMethodError) org.aspectj.weaver.bcel.BcelWorld.setTiming(ZZ)V
+org.aspectj.weaver.bcel.BcelWorld.setTiming(ZZ)V
+java.lang.NoSuchMethodError: org.aspectj.weaver.bcel.BcelWorld.setTiming(ZZ)V
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.initBcelWorld(AjBuildManager.java:831)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:245)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:181)
+ at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112)
+ at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
+ at org.aspectj.tools.ajc.Main.run(Main.java:371)
+ at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
+ at org.codehaus.mojo.aspectj.AbstractAjcCompiler.execute(AbstractAjcCompiler.java:405)
+ at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
+ at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
+ at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
+ at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
+ at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
+ at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:601)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
+
+---- org.aspectj.weaver.bcel.BcelWorld@6449abe0 ----
+Shadow mungers:
+Empty
+Type mungers:
+Empty
+Late Type mungers:
+Empty
diff --git a/ch05/ch06/aspectj-project/ajcore.20121210.235527.928.txt b/ch05/ch06/aspectj-project/ajcore.20121210.235527.928.txt
new file mode 100644
index 0000000..e2055a3
--- /dev/null
+++ b/ch05/ch06/aspectj-project/ajcore.20121210.235527.928.txt
@@ -0,0 +1,151 @@
+---- AspectJ Properties ---
+AspectJ Compiler 1.6.4 built on Monday Apr 20, 2009 at 16:48:12 GMT
+---- Dump Properties ---
+Dump file: ajcore.20121210.235527.928.txt
+Dump reason: java.lang.NoSuchMethodError
+Dump on exception: true
+Dump at exit condition: abort
+---- Exception Information ---
+java.lang.NoSuchMethodError: org.aspectj.weaver.bcel.BcelWorld.setTiming(ZZ)V
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.initBcelWorld(AjBuildManager.java:831)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:245)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:181)
+ at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112)
+ at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
+ at org.aspectj.tools.ajc.Main.run(Main.java:371)
+ at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
+ at org.codehaus.mojo.aspectj.AbstractAjcCompiler.execute(AbstractAjcCompiler.java:405)
+ at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
+ at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
+ at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
+ at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
+ at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
+ at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:601)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
+---- System Properties ---
+java.runtime.name=Java(TM) SE Runtime Environment
+sun.boot.library.path=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib
+java.vm.version=23.1-b03
+user.country.format=GB
+gopherProxySet=false
+java.vm.vendor=Oracle Corporation
+java.vendor.url=http://java.oracle.com/
+guice.disable.misplaced.annotation.check=true
+path.separator=:
+java.vm.name=Java HotSpot(TM) 64-Bit Server VM
+file.encoding.pkg=sun.io
+user.country=US
+sun.java.launcher=SUN_STANDARD
+sun.os.patch.level=unknown
+java.vm.specification.name=Java Virtual Machine Specification
+user.dir=/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project
+java.runtime.version=1.7.0_05-b05
+java.awt.graphicsenv=sun.awt.CGraphicsEnvironment
+java.endorsed.dirs=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/endorsed
+os.arch=x86_64
+java.io.tmpdir=/var/folders/fn/1lyy5y556l11ghf7sc4tvvrw0000gn/T/
+line.separator=
+
+java.vm.specification.vendor=Oracle Corporation
+os.name=Mac OS X
+classworlds.conf=/usr/share/maven/bin/m2.conf
+sun.jnu.encoding=UTF-8
+java.library.path=/Users/cscarioni/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
+java.specification.name=Java Platform API Specification
+java.class.version=51.0
+sun.management.compiler=HotSpot 64-Bit Tiered Compilers
+os.version=10.7.5
+http.nonProxyHosts=local|*.local|169.254/16|*.169.254/16
+user.home=/Users/cscarioni
+user.timezone=Europe/London
+java.awt.printerjob=sun.lwawt.macosx.CPrinterJob
+file.encoding=UTF-8
+java.specification.version=1.7
+java.class.path=/usr/share/maven/boot/plexus-classworlds-2.4.jar
+user.name=cscarioni
+java.vm.specification.version=1.7
+sun.java.command=org.codehaus.plexus.classworlds.launcher.Launcher aspectj:compile
+java.home=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre
+sun.arch.data.model=64
+user.language=en
+java.specification.vendor=Oracle Corporation
+awt.toolkit=sun.lwawt.macosx.LWCToolkit
+java.vm.info=mixed mode
+java.version=1.7.0_05
+java.ext.dirs=/Users/cscarioni/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
+sun.boot.class.path=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/JObjC.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes
+java.vendor=Oracle Corporation
+maven.home=/usr/share/maven
+file.separator=/
+java.vendor.url.bug=http://bugreport.sun.com/bugreport/
+sun.io.unicode.encoding=UnicodeBig
+sun.cpu.endian=little
+socksNonProxyHosts=local|*.local|169.254/16|*.169.254/16
+ftp.nonProxyHosts=local|*.local|169.254/16|*.169.254/16
+sun.cpu.isalist=
+---- Command Line ---
+-classpath
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+-d
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/Service.java
+---- Full Classpath ---
+Empty
+---- Compiler Messages ---
+warning couldn't find aspectjrt.jar on classpath, checked: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/JObjC.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/System/Library/Java/Extensions/AppleScriptEngine.jar:/System/Library/Java/Extensions/dns_sd.jar:/System/Library/Java/Extensions/j3daudio.jar:/System/Library/Java/Extensions/j3dcore.jar:/System/Library/Java/Extensions/j3dutils.jar:/System/Library/Java/Extensions/jai_codec.jar:/System/Library/Java/Extensions/jai_core.jar:/System/Library/Java/Extensions/mlibwrapper_jai.jar:/System/Library/Java/Extensions/MRJToolkit.jar:/System/Library/Java/Extensions/QTJava.zip:/System/Library/Java/Extensions/vecmath.jar:/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+info directory classpath entry does not exist: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar
+info zipfile classpath entry does not exist: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes
+abort ABORT -- (NoSuchMethodError) org.aspectj.weaver.bcel.BcelWorld.setTiming(ZZ)V
+org.aspectj.weaver.bcel.BcelWorld.setTiming(ZZ)V
+java.lang.NoSuchMethodError: org.aspectj.weaver.bcel.BcelWorld.setTiming(ZZ)V
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.initBcelWorld(AjBuildManager.java:831)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:245)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:181)
+ at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112)
+ at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
+ at org.aspectj.tools.ajc.Main.run(Main.java:371)
+ at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
+ at org.codehaus.mojo.aspectj.AbstractAjcCompiler.execute(AbstractAjcCompiler.java:405)
+ at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
+ at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
+ at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
+ at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
+ at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
+ at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:601)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
+
+---- org.aspectj.weaver.bcel.BcelWorld@2ad45a89 ----
+Shadow mungers:
+Empty
+Type mungers:
+Empty
+Late Type mungers:
+Empty
diff --git a/ch05/ch06/aspectj-project/ajcore.20121210.235713.938.txt b/ch05/ch06/aspectj-project/ajcore.20121210.235713.938.txt
new file mode 100644
index 0000000..0f556a7
--- /dev/null
+++ b/ch05/ch06/aspectj-project/ajcore.20121210.235713.938.txt
@@ -0,0 +1,144 @@
+---- AspectJ Properties ---
+AspectJ Compiler 1.7.1 built on Thursday Sep 6, 2012 at 16:39:22 GMT
+---- Dump Properties ---
+Dump file: ajcore.20121210.235713.938.txt
+Dump reason: java.lang.NoSuchMethodError
+Dump on exception: true
+Dump at exit condition: abort
+---- Exception Information ---
+java.lang.NoSuchMethodError: org.aspectj.weaver.bcel.BcelWorld.setErrorAndWarningThreshold(JJ)V
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.initBcelWorld(AjBuildManager.java:842)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:245)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:181)
+ at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112)
+ at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
+ at org.aspectj.tools.ajc.Main.run(Main.java:371)
+ at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
+ at org.codehaus.mojo.aspectj.AbstractAjcCompiler.execute(AbstractAjcCompiler.java:405)
+ at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
+ at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
+ at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
+ at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
+ at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
+ at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:601)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
+---- System Properties ---
+java.runtime.name=Java(TM) SE Runtime Environment
+sun.boot.library.path=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib
+java.vm.version=23.1-b03
+user.country.format=GB
+gopherProxySet=false
+java.vm.vendor=Oracle Corporation
+java.vendor.url=http://java.oracle.com/
+guice.disable.misplaced.annotation.check=true
+path.separator=:
+java.vm.name=Java HotSpot(TM) 64-Bit Server VM
+file.encoding.pkg=sun.io
+user.country=US
+sun.java.launcher=SUN_STANDARD
+sun.os.patch.level=unknown
+java.vm.specification.name=Java Virtual Machine Specification
+user.dir=/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project
+java.runtime.version=1.7.0_05-b05
+java.awt.graphicsenv=sun.awt.CGraphicsEnvironment
+java.endorsed.dirs=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/endorsed
+os.arch=x86_64
+java.io.tmpdir=/var/folders/fn/1lyy5y556l11ghf7sc4tvvrw0000gn/T/
+line.separator=
+
+java.vm.specification.vendor=Oracle Corporation
+os.name=Mac OS X
+classworlds.conf=/usr/share/maven/bin/m2.conf
+sun.jnu.encoding=UTF-8
+java.library.path=/Users/cscarioni/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
+java.specification.name=Java Platform API Specification
+java.class.version=51.0
+sun.management.compiler=HotSpot 64-Bit Tiered Compilers
+os.version=10.7.5
+http.nonProxyHosts=local|*.local|169.254/16|*.169.254/16
+user.home=/Users/cscarioni
+user.timezone=Europe/London
+java.awt.printerjob=sun.lwawt.macosx.CPrinterJob
+file.encoding=UTF-8
+java.specification.version=1.7
+java.class.path=/usr/share/maven/boot/plexus-classworlds-2.4.jar
+user.name=cscarioni
+java.vm.specification.version=1.7
+sun.java.command=org.codehaus.plexus.classworlds.launcher.Launcher aspectj:compile
+java.home=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre
+sun.arch.data.model=64
+user.language=en
+java.specification.vendor=Oracle Corporation
+awt.toolkit=sun.lwawt.macosx.LWCToolkit
+java.vm.info=mixed mode
+java.version=1.7.0_05
+java.ext.dirs=/Users/cscarioni/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
+sun.boot.class.path=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/JObjC.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes
+java.vendor=Oracle Corporation
+maven.home=/usr/share/maven
+file.separator=/
+java.vendor.url.bug=http://bugreport.sun.com/bugreport/
+sun.io.unicode.encoding=UnicodeBig
+sun.cpu.endian=little
+socksNonProxyHosts=local|*.local|169.254/16|*.169.254/16
+ftp.nonProxyHosts=local|*.local|169.254/16|*.169.254/16
+sun.cpu.isalist=
+---- Command Line ---
+-classpath
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+-d
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/Service.java
+---- Full Classpath ---
+Empty
+---- Compiler Messages ---
+warning couldn't find aspectjrt.jar on classpath, checked: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/JObjC.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/System/Library/Java/Extensions/AppleScriptEngine.jar:/System/Library/Java/Extensions/dns_sd.jar:/System/Library/Java/Extensions/j3daudio.jar:/System/Library/Java/Extensions/j3dcore.jar:/System/Library/Java/Extensions/j3dutils.jar:/System/Library/Java/Extensions/jai_codec.jar:/System/Library/Java/Extensions/jai_core.jar:/System/Library/Java/Extensions/mlibwrapper_jai.jar:/System/Library/Java/Extensions/MRJToolkit.jar:/System/Library/Java/Extensions/QTJava.zip:/System/Library/Java/Extensions/vecmath.jar:/Users/cscarioni/projects/pro-spring-security/src/ch06/aspectj-project/target/classes
+info directory classpath entry does not exist: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/lib/sunrsasign.jar
+info zipfile classpath entry does not exist: /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/jre/classes
+abort ABORT -- (NoSuchMethodError) org.aspectj.weaver.bcel.BcelWorld.setErrorAndWarningThreshold(JJ)V
+org.aspectj.weaver.bcel.BcelWorld.setErrorAndWarningThreshold(JJ)V
+java.lang.NoSuchMethodError: org.aspectj.weaver.bcel.BcelWorld.setErrorAndWarningThreshold(JJ)V
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.initBcelWorld(AjBuildManager.java:842)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:245)
+ at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:181)
+ at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112)
+ at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
+ at org.aspectj.tools.ajc.Main.run(Main.java:371)
+ at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
+ at org.codehaus.mojo.aspectj.AbstractAjcCompiler.execute(AbstractAjcCompiler.java:405)
+ at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
+ at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
+ at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
+ at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
+ at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
+ at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
+ at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
+ at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
+ at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:601)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
+ at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
+
diff --git a/ch05/ch06/aspectj-project/pom.xml b/ch05/ch06/aspectj-project/pom.xml
new file mode 100644
index 0000000..401ad5a
--- /dev/null
+++ b/ch05/ch06/aspectj-project/pom.xml
@@ -0,0 +1,143 @@
+
+ 4.0.0
+ com.apress.pss
+ aspectj-project
+ war
+ 1.0-SNAPSHOT
+ aspectj-project Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.2.RELEASE
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+ org.aspectj
+ aspectjweaver
+ 1.7.0
+
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ org.aspectj
+ aspectjrt
+ 1.7.1
+
+
+ org.springframework.security
+ spring-security-aspects
+ 3.1.3.RELEASE
+
+
+
+ aspectj-project
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.6
+ true
+ 1.6
+ 1.6
+
+
+
+
+ org.codehaus.mojo
+ aspectj-maven-plugin
+ 1.4
+
+
+ compile
+
+ 1.6
+ 1.6
+ false
+ true
+
+
+ org.springframework.security
+ spring-security-aspects
+
+
+
+
+ compile
+
+
+
+ test-compile
+
+ 1.6
+ 1.6
+ false
+
+
+ org.springframework.security
+ spring-security-aspects
+
+
+
+
+ test-compile
+
+
+
+
+
+ org.aspectj
+ aspectjrt
+ 1.7.1
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+
+
diff --git a/ch05/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/Service.java b/ch05/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/Service.java
new file mode 100644
index 0000000..5971ae6
--- /dev/null
+++ b/ch05/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/Service.java
@@ -0,0 +1,15 @@
+package com.apress.pss.aspects;
+
+import org.springframework.security.access.annotation.Secured;
+
+@org.springframework.stereotype.Service
+public class Service {
+ public String methodA() {
+ return methodB();
+ }
+
+ @Secured("ROLE_USER")
+ private String methodB() {
+ return "AspectJ Secured String";
+ }
+}
diff --git a/ch05/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/controllers/TheController.java b/ch05/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/controllers/TheController.java
new file mode 100644
index 0000000..6be625b
--- /dev/null
+++ b/ch05/ch06/aspectj-project/src/main/java/com/apress/pss/aspects/controllers/TheController.java
@@ -0,0 +1,20 @@
+package com.apress.pss.aspects.controllers;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import com.apress.pss.aspects.Service;
+
+@Controller
+@RequestMapping("/hello")
+public class TheController {
+
+ @Autowired
+ private Service service;
+
+ @RequestMapping("/")
+ public String doSomething(){
+ return service.methodA();
+ }
+}
diff --git a/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..122ba96
--- /dev/null
+++ b/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/aspect-example-servlet.xml b/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/aspect-example-servlet.xml
new file mode 100644
index 0000000..1ea7367
--- /dev/null
+++ b/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/aspect-example-servlet.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/web.xml b/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..aa75886
--- /dev/null
+++ b/ch05/ch06/aspectj-project/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ aspect-example
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ aspect-example
+ /
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
+
+
diff --git a/ch05/ch06/aspectj-project/src/main/webapp/index.jsp b/ch05/ch06/aspectj-project/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch05/ch06/aspectj-project/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch05/ch06/terrormovies-service-level/.classpath b/ch05/ch06/terrormovies-service-level/.classpath
new file mode 100644
index 0000000..30daf94
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/ch05/ch06/terrormovies-service-level/.project b/ch05/ch06/terrormovies-service-level/.project
new file mode 100644
index 0000000..9cecbe7
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/.project
@@ -0,0 +1,35 @@
+
+
+ terrormovies-service
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+
+
diff --git a/ch05/ch06/terrormovies-service-level/.settings/org.eclipse.jdt.core.prefs b/ch05/ch06/terrormovies-service-level/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..107056a
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/ch05/ch06/terrormovies-service-level/.settings/org.eclipse.m2e.core.prefs b/ch05/ch06/terrormovies-service-level/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch05/ch06/terrormovies-service-level/pom.xml b/ch05/ch06/terrormovies-service-level/pom.xml
new file mode 100644
index 0000000..f4ba752
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/pom.xml
@@ -0,0 +1,100 @@
+
+ 4.0.0
+ com.apress.pss
+ terrormovies-service
+ war
+ 0.0.1-SNAPSHOT
+ terrormovies Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-taglibs
+ 3.1.2.RELEASE
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+ org.aspectj
+ aspectjweaver
+ 1.7.0
+
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ javax.servlet.jsp
+ jsp-api
+ 2.1
+
+
+ javax.servlet
+ jstl
+ 1.2
+
+
+ javax.annotation
+ jsr250-api
+ 1.0
+
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ terrormovies
+
+
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/access/AccessOperations.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/access/AccessOperations.java
new file mode 100644
index 0000000..af88353
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/access/AccessOperations.java
@@ -0,0 +1,7 @@
+package com.apress.pss.terrormovies.access;
+
+public interface AccessOperations {
+ void login(String username, String password);
+ void logout();
+ String executeOperation(String beanName, String method);
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/access/AccessOperationsImpl.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/access/AccessOperationsImpl.java
new file mode 100644
index 0000000..e052c46
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/access/AccessOperationsImpl.java
@@ -0,0 +1,61 @@
+package com.apress.pss.terrormovies.access;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+public class AccessOperationsImpl implements AccessOperations, ApplicationContextAware {
+
+ private AuthenticationManager authenticationManager;
+ private ApplicationContext context;
+
+ public AccessOperationsImpl(){
+ SecurityContextHolder.setStrategyName("MODE_GLOBAL");
+ initAnonymous();
+
+ }
+
+ public void login(String username, String password) {
+ UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
+ username, password);
+ Authentication authentication = authenticationManager.authenticate(authRequest);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
+
+ public void logout() {
+ SecurityContextHolder.clearContext();
+ initAnonymous();
+ }
+
+ public String executeOperation(String beanName, String method) {
+ Object bean = context.getBean(beanName);
+ Object result = null;
+ try {
+ result = bean.getClass().getMethod(method).invoke(bean);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ return result.toString();
+ }
+
+ public void setApplicationContext(ApplicationContext context)
+ throws BeansException {
+ this.context = context;
+ }
+
+ public void setAuthenticationManager(AuthenticationManager authenticationManager) {
+ this.authenticationManager = authenticationManager;
+ }
+
+ private void initAnonymous() {
+ AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken("anonymous", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
+ SecurityContextHolder.getContext().setAuthentication(auth);
+ }
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java
new file mode 100644
index 0000000..c2b72ff
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java
@@ -0,0 +1,20 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+
+@RequestMapping("/admin")
+public interface AdminController {
+
+ @RequestMapping(method = RequestMethod.POST, value = "/movies")
+ @ResponseBody
+ public abstract String createMovie(@RequestBody String movie);
+
+ @RequestMapping(method = RequestMethod.GET, value = "/movies")
+ @ResponseBody
+ public abstract String createMovie();
+
+}
\ No newline at end of file
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/AdminControllerImpl.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/AdminControllerImpl.java
new file mode 100644
index 0000000..9929f60
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/AdminControllerImpl.java
@@ -0,0 +1,33 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.security.access.annotation.Secured;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.apress.pss.terrormovies.model.User;
+
+@Controller
+@RequestMapping("/admin")
+public class AdminControllerImpl implements AdminController{
+
+ @RequestMapping(method = RequestMethod.POST, value = "/movies")
+ @ResponseBody
+ @Secured("ROLE_ADMIN")
+ public String createMovie(@RequestBody String movie) {
+ System.out.println("Adding movie!! "+movie);
+ return "created";
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/movies")
+ @ResponseBody
+ @Secured("ROLE_ADMIN")
+ public String createMovie() {
+ User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ System.out.println("returned movie!");
+ return "User "+user.getLastname()+" is accessing movie x";
+ }
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java
new file mode 100644
index 0000000..0929f11
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java
@@ -0,0 +1,16 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+
+@Controller
+@RequestMapping("")
+public class LoginController {
+ @RequestMapping(method = RequestMethod.GET, value = "/custom_login")
+ public String showLogin(){
+ return "login";
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java
new file mode 100644
index 0000000..e492e1a
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java
@@ -0,0 +1,49 @@
+package com.apress.pss.terrormovies.controller;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.apress.pss.terrormovies.model.Movie;
+import com.apress.pss.terrormovies.service.MoviesService;
+
+@Controller
+@RequestMapping("/movies")
+public class MovieController {
+
+ @Autowired
+ private MoviesService moviesService;
+
+ @RequestMapping(method = RequestMethod.GET, value = "/{name}")
+ @ResponseBody
+ public String getMovieByName(@PathVariable String name){
+ Movie movie = moviesService.getMovieByName(name);
+ return movie.toString();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/")
+ public ModelAndView getAllMovies(){
+ ModelAndView mv = new ModelAndView("allMovies");
+ mv.addObject("movies", moviesService.getAllMovies());
+ return mv;
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/new")
+ public String showForm(){
+ return "newMovies";
+ }
+ @RequestMapping(method = RequestMethod.POST, value = "/new")
+ public String newMovies(@RequestParam String csvMovies){
+ String[] movies = csvMovies.split(",");
+ moviesService.addNewMovies(new ArrayList(Arrays.asList(movies)));
+ return "newMovies";
+ }
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/model/Movie.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/model/Movie.java
new file mode 100644
index 0000000..4f56649
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/model/Movie.java
@@ -0,0 +1,26 @@
+package com.apress.pss.terrormovies.model;
+
+public class Movie {
+ private String name;
+ private String budget;
+
+
+ public Movie(String name, String budget) {
+ super();
+ this.name = name;
+ this.budget = budget;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getBudget() {
+ return budget;
+ }
+
+ public String toString(){
+ return "Title: "+name+"; Budget: "+budget;
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/model/User.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/model/User.java
new file mode 100644
index 0000000..dfe0396
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/model/User.java
@@ -0,0 +1,34 @@
+package com.apress.pss.terrormovies.model;
+
+import java.util.Collection;
+
+import org.springframework.security.core.GrantedAuthority;
+
+public class User extends org.springframework.security.core.userdetails.User{
+
+ private String lastname;
+ private int age;
+
+ public User(String username, String password, boolean enabled,
+ boolean accountNonExpired, boolean credentialsNonExpired,
+ boolean accountNonLocked,
+ Collection extends GrantedAuthority> authorities, String lastname, int age) {
+ super(username, password, enabled, accountNonExpired, credentialsNonExpired,
+ accountNonLocked, authorities);
+ this.lastname = lastname;
+ this.age=age;
+ }
+
+ public User(String username, String password, Collection extends GrantedAuthority> authorities, String lastname, int age) {
+ this(username, password, true, true, true, true, authorities, lastname,age);
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java
new file mode 100644
index 0000000..9f12e99
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java
@@ -0,0 +1,18 @@
+package com.apress.pss.terrormovies.security;
+
+import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
+import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.FilterInvocation;
+
+public class CustomWebSecurityExpressionHandler extends AbstractSecurityExpressionHandler {
+
+ @Override
+ protected SecurityExpressionRoot createSecurityExpressionRoot(
+ Authentication authentication, FilterInvocation invocation) {
+ CustomWebSecurityExpressionRoot root = new CustomWebSecurityExpressionRoot(authentication, invocation);
+ root.setPermissionEvaluator(getPermissionEvaluator());
+ return root;
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java
new file mode 100644
index 0000000..c305cab
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java
@@ -0,0 +1,20 @@
+package com.apress.pss.terrormovies.security;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.expression.WebSecurityExpressionRoot;
+
+import com.apress.pss.terrormovies.model.User;
+
+public class CustomWebSecurityExpressionRoot extends WebSecurityExpressionRoot{
+
+ public CustomWebSecurityExpressionRoot(Authentication a, FilterInvocation fi) {
+ super(a, fi);
+ }
+
+ public boolean isOver18(){
+ User user = (User)this.getPrincipal();
+ return user.getAge() >= 18;
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java
new file mode 100644
index 0000000..f725647
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java
@@ -0,0 +1,21 @@
+package com.apress.pss.terrormovies.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+
+public class ServerErrorFailureHandler implements AuthenticationFailureHandler{
+
+ public void onAuthenticationFailure(HttpServletRequest request,
+ HttpServletResponse response, AuthenticationException exception)
+ throws IOException, ServletException {
+ response.sendError(500);
+
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/service/MoviesService.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/service/MoviesService.java
new file mode 100644
index 0000000..fd308ca
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/service/MoviesService.java
@@ -0,0 +1,14 @@
+package com.apress.pss.terrormovies.service;
+
+import java.util.Collection;
+import java.util.List;
+
+import com.apress.pss.terrormovies.model.Movie;
+
+public interface MoviesService {
+ Movie getMovieByName(String name);
+
+ void addNewMovies(List movies);
+
+ Collection getAllMovies();
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/service/MoviesServiceImpl.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/service/MoviesServiceImpl.java
new file mode 100644
index 0000000..7104b62
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/service/MoviesServiceImpl.java
@@ -0,0 +1,45 @@
+package com.apress.pss.terrormovies.service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.security.access.prepost.PostAuthorize;
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.access.prepost.PreFilter;
+
+import com.apress.pss.terrormovies.model.Movie;
+
+public class MoviesServiceImpl implements MoviesService{
+
+ private static final Map MOVIES = new HashMap();
+
+ static{
+ MOVIES.put("die hard", new Movie("Die Hard", "20000000"));
+ MOVIES.put("two days in paris", new Movie("two days in paris ", "1000000"));
+ }
+
+ //@PreAuthorize("#name.length() < 50 and hasRole('ROLE_USER')")
+ @PostAuthorize("T(java.lang.Integer).parseInt(getReturnObject().budget) < 5000000")
+ public Movie getMovieByName(String name) {
+ return MOVIES.get(name.toLowerCase());
+ }
+
+ //@PreAuthorize("hasRole('ROLE_ADMIN')")
+ //@PreFilter("not filterObject.contains('badword')")
+ public void addNewMovies(List movies) {
+ for(String movie: movies){
+ MOVIES.put(movie, new Movie(movie, "10000"));
+ }
+ }
+
+ //@PreAuthorize("isFullyAuthenticated()")
+ //@PostFilter("hasRole('ROLE_ADMIN') or (hasRole('ROLE_USER') and T(java.lang.Integer).parseInt(filterObject.budget) < 5000000)")
+ public Collection getAllMovies(){
+ return new ArrayList(MOVIES.values());
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java
new file mode 100644
index 0000000..54189e6
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java
@@ -0,0 +1,35 @@
+package com.apress.pss.terrormovies.spring;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+import com.apress.pss.terrormovies.model.User;
+
+public class CustomInMemoryUserDetailsManager implements UserDetailsService {
+
+ private Map users = new HashMap();
+
+ public CustomInMemoryUserDetailsManager(Collection users) {
+ for (User user : users) {
+ this.users.put(user.getUsername().toLowerCase(), user);
+ }
+ }
+
+ public UserDetails loadUserByUsername(String username)
+ throws UsernameNotFoundException {
+ User user = users.get(username.toLowerCase());
+
+ if (user == null) {
+ throw new UsernameNotFoundException(username);
+ }
+ User userNew = new User(user.getUsername(), user.getPassword(), user.getAuthorities(), user.getLastname(), user.getAge());
+
+ return userNew;
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/standalone/Main.java b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/standalone/Main.java
new file mode 100644
index 0000000..f2e8ad9
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/java/com/apress/pss/terrormovies/standalone/Main.java
@@ -0,0 +1,59 @@
+package com.apress.pss.terrormovies.standalone;
+
+import java.io.Console;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import com.apress.pss.terrormovies.access.AccessOperations;
+
+public class Main {
+
+ private AccessOperations operations;
+
+ public static void main(String[] args) {
+ Main main = new Main();
+ main.loadContext();
+ main.initCommandInput();
+ }
+
+ private void initCommandInput() {
+ Console c = System.console();
+ if (c == null) {
+ System.err.println("No console.");
+ System.exit(1);
+ }
+ String command = "";
+ do {
+ try {
+ command = c.readLine("Insert command: ");
+ interpretAndExecute(command);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } while (!command.equals("exit"));
+ }
+
+ private void interpretAndExecute(String command) {
+ if (command.equals("logout")) {
+ operations.logout();
+ } else if (command.startsWith("login")) {
+ String userAndPassword = command.split(" ")[1];
+ String user = userAndPassword.split(":")[0];
+ String password = userAndPassword.split(":")[1];
+ operations.login(user, password);
+ } else {
+ String[] beanAndMethod = command.split(" ");
+ String returned = operations.executeOperation(beanAndMethod[0], beanAndMethod[1]);
+ System.out.println("Returned: "+returned);
+ }
+ }
+
+ private void loadContext() {
+ ApplicationContext context = new ClassPathXmlApplicationContext(
+ "applicationContext-security.xml");
+ operations = context
+ .getBean("accessOperations", AccessOperations.class);
+ }
+
+}
diff --git a/ch05/ch06/terrormovies-service-level/src/main/resources/applicationContext-security.xml b/ch05/ch06/terrormovies-service-level/src/main/resources/applicationContext-security.xml
new file mode 100644
index 0000000..a5b7de8
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/resources/applicationContext-security.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..289337f
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/terrormovies-servlet.xml b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/terrormovies-servlet.xml
new file mode 100644
index 0000000..798da49
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/terrormovies-servlet.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/allMovies.jsp b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/allMovies.jsp
new file mode 100644
index 0000000..76b4b21
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/allMovies.jsp
@@ -0,0 +1,17 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib prefix="security"
+ uri="http://www.springframework.org/security/tags"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+
+Terror movies
+
+
+
+
+ ${movie.name}
+
+
+
\ No newline at end of file
diff --git a/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/login.jsp b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/login.jsp
new file mode 100644
index 0000000..ebb817a
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/login.jsp
@@ -0,0 +1,21 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+
+
+
+
+Terror movies
+
+
+ <% if(request.getParameter("error") != null){
+ out.println("ERROR LOGIN");
+ }
+ %>
+
+
+
\ No newline at end of file
diff --git a/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/movies.jsp b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/movies.jsp
new file mode 100644
index 0000000..f3fb673
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/movies.jsp
@@ -0,0 +1,26 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib prefix="security"
+ uri="http://www.springframework.org/security/tags"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+
+Terror movies
+
+
+ Mr
+
+
+
+ ${movie.name}
+
+
+ ${movie.budget}
+
+
+
+ You are a very appreciated VIP user
+
+
+
\ No newline at end of file
diff --git a/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/newMovies.jsp b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/newMovies.jsp
new file mode 100644
index 0000000..e829747
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/views/newMovies.jsp
@@ -0,0 +1,17 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib prefix="security"
+ uri="http://www.springframework.org/security/tags"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+
+Terror movies
+
+
+
+
+
\ No newline at end of file
diff --git a/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/web.xml b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..38fb1ce
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ terrormovies
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ terrormovies
+ /
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
+
+
diff --git a/ch05/ch06/terrormovies-service-level/src/main/webapp/index.jsp b/ch05/ch06/terrormovies-service-level/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch05/ch06/terrormovies-service-level/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch06/ch07/.DS_Store b/ch06/ch07/.DS_Store
new file mode 100644
index 0000000..e68ff72
Binary files /dev/null and b/ch06/ch07/.DS_Store differ
diff --git a/ch06/ch07/authentication-database/.DS_Store b/ch06/ch07/authentication-database/.DS_Store
new file mode 100644
index 0000000..d432ed5
Binary files /dev/null and b/ch06/ch07/authentication-database/.DS_Store differ
diff --git a/ch06/ch07/authentication-database/.classpath b/ch06/ch07/authentication-database/.classpath
new file mode 100644
index 0000000..30daf94
--- /dev/null
+++ b/ch06/ch07/authentication-database/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-database/.project b/ch06/ch07/authentication-database/.project
new file mode 100644
index 0000000..e2c16b2
--- /dev/null
+++ b/ch06/ch07/authentication-database/.project
@@ -0,0 +1,48 @@
+
+
+ pss01
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch06/ch07/authentication-database/.settings/.jsdtscope b/ch06/ch07/authentication-database/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch06/ch07/authentication-database/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-database/.settings/org.eclipse.jdt.core.prefs b/ch06/ch07/authentication-database/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch06/ch07/authentication-database/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch06/ch07/authentication-database/.settings/org.eclipse.m2e.core.prefs b/ch06/ch07/authentication-database/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch06/ch07/authentication-database/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch06/ch07/authentication-database/.settings/org.eclipse.wst.common.component b/ch06/ch07/authentication-database/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..249f6a7
--- /dev/null
+++ b/ch06/ch07/authentication-database/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch06/ch07/authentication-database/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch06/ch07/authentication-database/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..ef27789
--- /dev/null
+++ b/ch06/ch07/authentication-database/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-database/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch06/ch07/authentication-database/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch06/ch07/authentication-database/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch06/ch07/authentication-database/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch06/ch07/authentication-database/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch06/ch07/authentication-database/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch06/ch07/authentication-database/pom.xml b/ch06/ch07/authentication-database/pom.xml
new file mode 100644
index 0000000..d9caeaf
--- /dev/null
+++ b/ch06/ch07/authentication-database/pom.xml
@@ -0,0 +1,73 @@
+
+ 4.0.0
+ com.apress.pss
+ db-authentication
+ war
+ 1.0-SNAPSHOT
+ Database authentication
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ org.hsqldb
+ hsqldb
+ 2.2.8
+
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch06/ch07/authentication-database/src/.DS_Store b/ch06/ch07/authentication-database/src/.DS_Store
new file mode 100644
index 0000000..48bf7fa
Binary files /dev/null and b/ch06/ch07/authentication-database/src/.DS_Store differ
diff --git a/ch06/ch07/authentication-database/src/main/.DS_Store b/ch06/ch07/authentication-database/src/main/.DS_Store
new file mode 100644
index 0000000..9cf25de
Binary files /dev/null and b/ch06/ch07/authentication-database/src/main/.DS_Store differ
diff --git a/ch06/ch07/authentication-database/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch06/ch07/authentication-database/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch06/ch07/authentication-database/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch06/ch07/authentication-database/src/main/resources/security-schema.sql b/ch06/ch07/authentication-database/src/main/resources/security-schema.sql
new file mode 100644
index 0000000..d5155a9
--- /dev/null
+++ b/ch06/ch07/authentication-database/src/main/resources/security-schema.sql
@@ -0,0 +1,19 @@
+CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,
+ PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,
+ ENABLED BOOLEAN NOT NULL);
+
+CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,
+ AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,
+ CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));
+
+CREATE TABLE GROUPS(id BIGINT NOT NULL PRIMARY KEY,
+ GROUP_NAME VARCHAR_IGNORECASE(50) NOT NULL);
+
+CREATE TABLE GROUP_MEMBERS(group_id BIGINT NOT NULL,
+ username VARCHAR_IGNORECASE(50) NOT NULL);
+
+CREATE TABLE GROUP_AUTHORITIES(group_id BIGINT NOT NULL,
+ authority VARCHAR_IGNORECASE(50) NOT NULL);
+
+COMMIT;
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-database/src/main/resources/users.sql b/ch06/ch07/authentication-database/src/main/resources/users.sql
new file mode 100644
index 0000000..2dfe0d1
--- /dev/null
+++ b/ch06/ch07/authentication-database/src/main/resources/users.sql
@@ -0,0 +1,5 @@
+INSERT INTO USERS VALUES('car','scarvarez',true);
+INSERT INTO GROUPS VALUES(1,'GROUP_MEMBERS_SCARV');
+INSERT INTO GROUP_MEMBERS VALUES(1,'car');
+INSERT INTO GROUP_AUTHORITIES VALUES(1,'ROLE_SCARVAREZ_MEMBER');
+COMMIT;
\ No newline at end of file
diff --git a/ch06/ch07/authentication-database/src/main/webapp/.DS_Store b/ch06/ch07/authentication-database/src/main/webapp/.DS_Store
new file mode 100644
index 0000000..160729c
Binary files /dev/null and b/ch06/ch07/authentication-database/src/main/webapp/.DS_Store differ
diff --git a/ch06/ch07/authentication-database/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch06/ch07/authentication-database/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..df1ad14
--- /dev/null
+++ b/ch06/ch07/authentication-database/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-database/src/main/webapp/WEB-INF/web.xml b/ch06/ch07/authentication-database/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch06/ch07/authentication-database/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-jaas/example/.classpath b/ch06/ch07/authentication-jaas/example/.classpath
new file mode 100644
index 0000000..30daf94
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-jaas/example/.project b/ch06/ch07/authentication-jaas/example/.project
new file mode 100644
index 0000000..7c3c059
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.project
@@ -0,0 +1,48 @@
+
+
+ terrormovies
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch06/ch07/authentication-jaas/example/.settings/.jsdtscope b/ch06/ch07/authentication-jaas/example/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.jdt.core.prefs b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.m2e.core.prefs b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.common.component b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..43127a5
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch06/ch07/authentication-jaas/example/jetty-ssl.truststore b/ch06/ch07/authentication-jaas/example/jetty-ssl.truststore
new file mode 100644
index 0000000..f9c21bd
Binary files /dev/null and b/ch06/ch07/authentication-jaas/example/jetty-ssl.truststore differ
diff --git a/ch06/ch07/authentication-jaas/example/pom.xml b/ch06/ch07/authentication-jaas/example/pom.xml
new file mode 100644
index 0000000..e75f303
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/pom.xml
@@ -0,0 +1,127 @@
+
+ 4.0.0
+ com.apress.pss
+ authentication-jaas
+ war
+ 0.0.1-SNAPSHOT
+ jaas Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-taglibs
+ 3.1.3.RELEASE
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ javax.servlet.jsp
+ jsp-api
+ 2.1
+
+
+ javax.servlet
+ jstl
+ 1.2
+
+
+
+
+
+
+ org.codehaus.mojo
+ keytool-maven-plugin
+
+
+ generate-resources
+ clean
+
+ clean
+
+
+
+ generate-resources
+ genkey
+
+ genkey
+
+
+
+
+ ${project.build.directory}/jetty-ssl.keystore
+ cn=apress.pss
+ jetty8
+ jetty8
+ jetty6
+ RSA
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+ 8443
+ 60000
+ ${project.build.directory}/jetty-ssl.keystore
+ jetty-ssl.truststore
+ jetty8
+ jetty8
+ jetty8
+ true
+ true
+
+
+
+
+
+ jaas-test
+
+
diff --git a/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/security/RoleGranterFromMap.java b/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/security/RoleGranterFromMap.java
new file mode 100644
index 0000000..0a12604
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/security/RoleGranterFromMap.java
@@ -0,0 +1,22 @@
+package com.apress.pss.security;
+
+import java.security.Principal;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.security.authentication.jaas.AuthorityGranter;
+
+public class RoleGranterFromMap implements AuthorityGranter {
+
+ private static Map USER_ROLES = new HashMap();
+
+ static {
+ USER_ROLES.put("car", "ROLE_ADMINISTRATOR");
+ }
+
+ public Set grant(Principal principal) {
+ return Collections.singleton(USER_ROLES.get(principal.getName()));
+ }
+}
diff --git a/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/security/SampleLoginModule.java b/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/security/SampleLoginModule.java
new file mode 100644
index 0000000..33b3b5c
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/security/SampleLoginModule.java
@@ -0,0 +1,81 @@
+package com.apress.pss.security;
+
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+public class SampleLoginModule implements LoginModule {
+
+ private Subject subject;
+ private String password;
+ private String username;
+ private static Map USER_PASSWORDS = new HashMap();
+
+ static {
+ USER_PASSWORDS.put("car", "scarvarez");
+ }
+
+ public boolean abort() throws LoginException {
+ return true;
+ }
+
+ public boolean commit() throws LoginException {
+ return true;
+ }
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map sharedState, Map options) {
+ this.subject = subject;
+
+ try {
+ NameCallback nameCallback = new NameCallback("prompt");
+ PasswordCallback passwordCallback = new PasswordCallback("prompt",
+ false);
+
+ callbackHandler.handle(new Callback[] { nameCallback,
+ passwordCallback });
+
+ this.password = new String(passwordCallback.getPassword());
+ this.username = nameCallback.getName();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean login() throws LoginException {
+
+ if (USER_PASSWORDS.get(username) == null
+ || !USER_PASSWORDS.get(username).equals(password)) {
+ throw new LoginException("username is not equal to password");
+ }
+
+ subject.getPrincipals().add(new CustomPrincipal(username));
+ return true;
+ }
+
+ public boolean logout() throws LoginException {
+ return true;
+ }
+
+ private static class CustomPrincipal implements Principal, Serializable {
+ private final String username;
+
+ public CustomPrincipal(String username) {
+ this.username = username;
+ }
+
+ public String getName() {
+ return username;
+ }
+ }
+
+}
diff --git a/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch06/ch07/authentication-jaas/example/src/main/resources/pss_jaas.config b/ch06/ch07/authentication-jaas/example/src/main/resources/pss_jaas.config
new file mode 100644
index 0000000..028f674
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/resources/pss_jaas.config
@@ -0,0 +1,3 @@
+Pss {
+ com.apress.pss.security.SampleLoginModule required;
+};
\ No newline at end of file
diff --git a/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..3ba1f59
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/views/login.jsp b/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/views/login.jsp
new file mode 100644
index 0000000..ebb817a
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/views/login.jsp
@@ -0,0 +1,21 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+
+
+
+
+Terror movies
+
+
+ <% if(request.getParameter("error") != null){
+ out.println("ERROR LOGIN");
+ }
+ %>
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/views/movies.jsp b/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/views/movies.jsp
new file mode 100644
index 0000000..f3fb673
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/views/movies.jsp
@@ -0,0 +1,26 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib prefix="security"
+ uri="http://www.springframework.org/security/tags"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+
+Terror movies
+
+
+ Mr
+
+
+
+ ${movie.name}
+
+
+ ${movie.budget}
+
+
+
+ You are a very appreciated VIP user
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/web.xml b/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-jaas/example/src/main/webapp/index.jsp b/ch06/ch07/authentication-jaas/example/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch06/ch07/authentication-jaas/example/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch06/ch07/authentication-ldap/.DS_Store b/ch06/ch07/authentication-ldap/.DS_Store
new file mode 100644
index 0000000..d432ed5
Binary files /dev/null and b/ch06/ch07/authentication-ldap/.DS_Store differ
diff --git a/ch06/ch07/authentication-ldap/.classpath b/ch06/ch07/authentication-ldap/.classpath
new file mode 100644
index 0000000..30daf94
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-ldap/.project b/ch06/ch07/authentication-ldap/.project
new file mode 100644
index 0000000..e2c16b2
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.project
@@ -0,0 +1,48 @@
+
+
+ pss01
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch06/ch07/authentication-ldap/.settings/.jsdtscope b/ch06/ch07/authentication-ldap/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-ldap/.settings/org.eclipse.jdt.core.prefs b/ch06/ch07/authentication-ldap/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch06/ch07/authentication-ldap/.settings/org.eclipse.m2e.core.prefs b/ch06/ch07/authentication-ldap/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.common.component b/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..249f6a7
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..ef27789
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch06/ch07/authentication-ldap/pom.xml b/ch06/ch07/authentication-ldap/pom.xml
new file mode 100644
index 0000000..33f7175
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/pom.xml
@@ -0,0 +1,78 @@
+
+ 4.0.0
+ com.apress.pss
+ ldap-authentication
+ war
+ 1.0-SNAPSHOT
+ Ldap authentication
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-ldap
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ org.hsqldb
+ hsqldb
+ 2.2.8
+
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch06/ch07/authentication-ldap/src/.DS_Store b/ch06/ch07/authentication-ldap/src/.DS_Store
new file mode 100644
index 0000000..48bf7fa
Binary files /dev/null and b/ch06/ch07/authentication-ldap/src/.DS_Store differ
diff --git a/ch06/ch07/authentication-ldap/src/main/.DS_Store b/ch06/ch07/authentication-ldap/src/main/.DS_Store
new file mode 100644
index 0000000..9cf25de
Binary files /dev/null and b/ch06/ch07/authentication-ldap/src/main/.DS_Store differ
diff --git a/ch06/ch07/authentication-ldap/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch06/ch07/authentication-ldap/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch06/ch07/authentication-ldap/src/main/resources/security-schema.sql b/ch06/ch07/authentication-ldap/src/main/resources/security-schema.sql
new file mode 100644
index 0000000..d5155a9
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/src/main/resources/security-schema.sql
@@ -0,0 +1,19 @@
+CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,
+ PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,
+ ENABLED BOOLEAN NOT NULL);
+
+CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,
+ AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,
+ CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));
+
+CREATE TABLE GROUPS(id BIGINT NOT NULL PRIMARY KEY,
+ GROUP_NAME VARCHAR_IGNORECASE(50) NOT NULL);
+
+CREATE TABLE GROUP_MEMBERS(group_id BIGINT NOT NULL,
+ username VARCHAR_IGNORECASE(50) NOT NULL);
+
+CREATE TABLE GROUP_AUTHORITIES(group_id BIGINT NOT NULL,
+ authority VARCHAR_IGNORECASE(50) NOT NULL);
+
+COMMIT;
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-ldap/src/main/resources/users.sql b/ch06/ch07/authentication-ldap/src/main/resources/users.sql
new file mode 100644
index 0000000..2dfe0d1
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/src/main/resources/users.sql
@@ -0,0 +1,5 @@
+INSERT INTO USERS VALUES('car','scarvarez',true);
+INSERT INTO GROUPS VALUES(1,'GROUP_MEMBERS_SCARV');
+INSERT INTO GROUP_MEMBERS VALUES(1,'car');
+INSERT INTO GROUP_AUTHORITIES VALUES(1,'ROLE_SCARVAREZ_MEMBER');
+COMMIT;
\ No newline at end of file
diff --git a/ch06/ch07/authentication-ldap/src/main/webapp/.DS_Store b/ch06/ch07/authentication-ldap/src/main/webapp/.DS_Store
new file mode 100644
index 0000000..160729c
Binary files /dev/null and b/ch06/ch07/authentication-ldap/src/main/webapp/.DS_Store differ
diff --git a/ch06/ch07/authentication-ldap/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch06/ch07/authentication-ldap/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..27bc062
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-ldap/src/main/webapp/WEB-INF/web.xml b/ch06/ch07/authentication-ldap/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch06/ch07/authentication-ldap/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-openid/.DS_Store b/ch06/ch07/authentication-openid/.DS_Store
new file mode 100644
index 0000000..d432ed5
Binary files /dev/null and b/ch06/ch07/authentication-openid/.DS_Store differ
diff --git a/ch06/ch07/authentication-openid/.classpath b/ch06/ch07/authentication-openid/.classpath
new file mode 100644
index 0000000..30daf94
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-openid/.project b/ch06/ch07/authentication-openid/.project
new file mode 100644
index 0000000..e2c16b2
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.project
@@ -0,0 +1,48 @@
+
+
+ pss01
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch06/ch07/authentication-openid/.settings/.jsdtscope b/ch06/ch07/authentication-openid/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-openid/.settings/org.eclipse.jdt.core.prefs b/ch06/ch07/authentication-openid/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch06/ch07/authentication-openid/.settings/org.eclipse.m2e.core.prefs b/ch06/ch07/authentication-openid/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.common.component b/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..249f6a7
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..ef27789
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch06/ch07/authentication-openid/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch06/ch07/authentication-openid/pom.xml b/ch06/ch07/authentication-openid/pom.xml
new file mode 100644
index 0000000..a165564
--- /dev/null
+++ b/ch06/ch07/authentication-openid/pom.xml
@@ -0,0 +1,89 @@
+
+ 4.0.0
+ com.apress.pss
+ openid-authentication
+ war
+ 1.0-SNAPSHOT
+ OpenId authentication
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-ldap
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-openid
+ 3.1.3.RELEASE
+
+
+ net.sourceforge.nekohtml
+ nekohtml
+ 1.9.16
+
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ org.hsqldb
+ hsqldb
+ 2.2.8
+
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch06/ch07/authentication-openid/src/.DS_Store b/ch06/ch07/authentication-openid/src/.DS_Store
new file mode 100644
index 0000000..48bf7fa
Binary files /dev/null and b/ch06/ch07/authentication-openid/src/.DS_Store differ
diff --git a/ch06/ch07/authentication-openid/src/main/.DS_Store b/ch06/ch07/authentication-openid/src/main/.DS_Store
new file mode 100644
index 0000000..9cf25de
Binary files /dev/null and b/ch06/ch07/authentication-openid/src/main/.DS_Store differ
diff --git a/ch06/ch07/authentication-openid/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch06/ch07/authentication-openid/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch06/ch07/authentication-openid/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch06/ch07/authentication-openid/src/main/webapp/.DS_Store b/ch06/ch07/authentication-openid/src/main/webapp/.DS_Store
new file mode 100644
index 0000000..160729c
Binary files /dev/null and b/ch06/ch07/authentication-openid/src/main/webapp/.DS_Store differ
diff --git a/ch06/ch07/authentication-openid/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch06/ch07/authentication-openid/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..bd1788f
--- /dev/null
+++ b/ch06/ch07/authentication-openid/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-openid/src/main/webapp/WEB-INF/web.xml b/ch06/ch07/authentication-openid/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch06/ch07/authentication-openid/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-x509/example/.classpath b/ch06/ch07/authentication-x509/example/.classpath
new file mode 100644
index 0000000..30daf94
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-x509/example/.project b/ch06/ch07/authentication-x509/example/.project
new file mode 100644
index 0000000..7c3c059
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.project
@@ -0,0 +1,48 @@
+
+
+ terrormovies
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch06/ch07/authentication-x509/example/.settings/.jsdtscope b/ch06/ch07/authentication-x509/example/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-x509/example/.settings/org.eclipse.jdt.core.prefs b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch06/ch07/authentication-x509/example/.settings/org.eclipse.m2e.core.prefs b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.common.component b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..43127a5
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch06/ch07/authentication-x509/example/jetty-ssl.truststore b/ch06/ch07/authentication-x509/example/jetty-ssl.truststore
new file mode 100644
index 0000000..f9c21bd
Binary files /dev/null and b/ch06/ch07/authentication-x509/example/jetty-ssl.truststore differ
diff --git a/ch06/ch07/authentication-x509/example/pom.xml b/ch06/ch07/authentication-x509/example/pom.xml
new file mode 100644
index 0000000..c418170
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/pom.xml
@@ -0,0 +1,127 @@
+
+ 4.0.0
+ com.apress.pss
+ authentication-x509
+ war
+ 0.0.1-SNAPSHOT
+ terrormovies Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-taglibs
+ 3.1.3.RELEASE
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ javax.servlet.jsp
+ jsp-api
+ 2.1
+
+
+ javax.servlet
+ jstl
+ 1.2
+
+
+
+
+
+
+ org.codehaus.mojo
+ keytool-maven-plugin
+
+
+ generate-resources
+ clean
+
+ clean
+
+
+
+ generate-resources
+ genkey
+
+ genkey
+
+
+
+
+ ${project.build.directory}/jetty-ssl.keystore
+ cn=apress.pss
+ jetty8
+ jetty8
+ jetty6
+ RSA
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+ 8443
+ 60000
+ ${project.build.directory}/jetty-ssl.keystore
+ jetty-ssl.truststore
+ jetty8
+ jetty8
+ jetty8
+ true
+ true
+
+
+
+
+
+ x509-test
+
+
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java
new file mode 100644
index 0000000..1be99a0
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/AdminController.java
@@ -0,0 +1,31 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.apress.pss.terrormovies.model.User;
+
+@Controller
+@RequestMapping("/admin")
+public class AdminController {
+
+ @RequestMapping(method = RequestMethod.POST, value = "/movies")
+ @ResponseBody
+ public String createMovie(@RequestBody String movie) {
+ System.out.println("Adding movie!! "+movie);
+ return "created";
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/movies")
+ @ResponseBody
+ public String createMovie() {
+ User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ System.out.println("returned movie!");
+ return "User "+user.getLastname()+" is accessing movie x";
+ }
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java
new file mode 100644
index 0000000..0929f11
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/LoginController.java
@@ -0,0 +1,16 @@
+package com.apress.pss.terrormovies.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+
+@Controller
+@RequestMapping("")
+public class LoginController {
+ @RequestMapping(method = RequestMethod.GET, value = "/custom_login")
+ public String showLogin(){
+ return "login";
+ }
+
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java
new file mode 100644
index 0000000..f828471
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/controller/MovieController.java
@@ -0,0 +1,46 @@
+package com.apress.pss.terrormovies.controller;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.apress.pss.terrormovies.model.Movie;
+
+@Controller
+@RequestMapping("/movies")
+public class MovieController {
+
+ private Map likedMovies;
+
+ public MovieController(){
+ likedMovies = new HashMap();
+ likedMovies.put(1, new String[]{"Die Hard", "Lethal Weapon"});
+ }
+ @RequestMapping(method = RequestMethod.GET, value = "/member/{id}")
+ @ResponseBody
+ public String getMoviesForMember(@PathVariable int id) {
+ StringBuilder builder = new StringBuilder();
+ for(String movie:likedMovies.get(id)){
+ builder.append(movie);
+ }
+ return builder.toString();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/")
+ public ModelAndView getAllMovies() {
+ ModelAndView mv = new ModelAndView("movies");
+ List movies = new ArrayList();
+ movies.add(new Movie("Die hard", "25000000"));
+ movies.add(new Movie("Lethatl Weapon", "30000000"));
+ mv.addObject("movies", movies);
+ return mv;
+ }
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/model/Movie.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/model/Movie.java
new file mode 100644
index 0000000..550267d
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/model/Movie.java
@@ -0,0 +1,22 @@
+package com.apress.pss.terrormovies.model;
+
+public class Movie {
+ private String name;
+ private String budget;
+
+
+ public Movie(String name, String budget) {
+ super();
+ this.name = name;
+ this.budget = budget;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getBudget() {
+ return budget;
+ }
+
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/model/User.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/model/User.java
new file mode 100644
index 0000000..dfe0396
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/model/User.java
@@ -0,0 +1,34 @@
+package com.apress.pss.terrormovies.model;
+
+import java.util.Collection;
+
+import org.springframework.security.core.GrantedAuthority;
+
+public class User extends org.springframework.security.core.userdetails.User{
+
+ private String lastname;
+ private int age;
+
+ public User(String username, String password, boolean enabled,
+ boolean accountNonExpired, boolean credentialsNonExpired,
+ boolean accountNonLocked,
+ Collection extends GrantedAuthority> authorities, String lastname, int age) {
+ super(username, password, enabled, accountNonExpired, credentialsNonExpired,
+ accountNonLocked, authorities);
+ this.lastname = lastname;
+ this.age=age;
+ }
+
+ public User(String username, String password, Collection extends GrantedAuthority> authorities, String lastname, int age) {
+ this(username, password, true, true, true, true, authorities, lastname,age);
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java
new file mode 100644
index 0000000..9f12e99
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionHandler.java
@@ -0,0 +1,18 @@
+package com.apress.pss.terrormovies.security;
+
+import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
+import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.FilterInvocation;
+
+public class CustomWebSecurityExpressionHandler extends AbstractSecurityExpressionHandler {
+
+ @Override
+ protected SecurityExpressionRoot createSecurityExpressionRoot(
+ Authentication authentication, FilterInvocation invocation) {
+ CustomWebSecurityExpressionRoot root = new CustomWebSecurityExpressionRoot(authentication, invocation);
+ root.setPermissionEvaluator(getPermissionEvaluator());
+ return root;
+ }
+
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java
new file mode 100644
index 0000000..c305cab
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/CustomWebSecurityExpressionRoot.java
@@ -0,0 +1,20 @@
+package com.apress.pss.terrormovies.security;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.expression.WebSecurityExpressionRoot;
+
+import com.apress.pss.terrormovies.model.User;
+
+public class CustomWebSecurityExpressionRoot extends WebSecurityExpressionRoot{
+
+ public CustomWebSecurityExpressionRoot(Authentication a, FilterInvocation fi) {
+ super(a, fi);
+ }
+
+ public boolean isOver18(){
+ User user = (User)this.getPrincipal();
+ return user.getAge() >= 18;
+ }
+
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java
new file mode 100644
index 0000000..f725647
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/security/ServerErrorFailureHandler.java
@@ -0,0 +1,21 @@
+package com.apress.pss.terrormovies.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+
+public class ServerErrorFailureHandler implements AuthenticationFailureHandler{
+
+ public void onAuthenticationFailure(HttpServletRequest request,
+ HttpServletResponse response, AuthenticationException exception)
+ throws IOException, ServletException {
+ response.sendError(500);
+
+ }
+
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java
new file mode 100644
index 0000000..54189e6
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/java/com/apress/pss/terrormovies/spring/CustomInMemoryUserDetailsManager.java
@@ -0,0 +1,35 @@
+package com.apress.pss.terrormovies.spring;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+import com.apress.pss.terrormovies.model.User;
+
+public class CustomInMemoryUserDetailsManager implements UserDetailsService {
+
+ private Map users = new HashMap();
+
+ public CustomInMemoryUserDetailsManager(Collection users) {
+ for (User user : users) {
+ this.users.put(user.getUsername().toLowerCase(), user);
+ }
+ }
+
+ public UserDetails loadUserByUsername(String username)
+ throws UsernameNotFoundException {
+ User user = users.get(username.toLowerCase());
+
+ if (user == null) {
+ throw new UsernameNotFoundException(username);
+ }
+ User userNew = new User(user.getUsername(), user.getPassword(), user.getAuthorities(), user.getLastname(), user.getAge());
+
+ return userNew;
+ }
+
+}
diff --git a/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..00c730f
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/views/login.jsp b/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/views/login.jsp
new file mode 100644
index 0000000..ebb817a
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/views/login.jsp
@@ -0,0 +1,21 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+
+
+
+
+Terror movies
+
+
+ <% if(request.getParameter("error") != null){
+ out.println("ERROR LOGIN");
+ }
+ %>
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/views/movies.jsp b/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/views/movies.jsp
new file mode 100644
index 0000000..f3fb673
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/views/movies.jsp
@@ -0,0 +1,26 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib prefix="security"
+ uri="http://www.springframework.org/security/tags"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+
+Terror movies
+
+
+ Mr
+
+
+
+ ${movie.name}
+
+
+ ${movie.budget}
+
+
+
+ You are a very appreciated VIP user
+
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/web.xml b/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch06/ch07/authentication-x509/example/src/main/webapp/index.jsp b/ch06/ch07/authentication-x509/example/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch06/ch07/authentication-x509/example/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/.classpath b/ch07/ch08/acl-example-from-scratch/.classpath
new file mode 100644
index 0000000..ae98bae
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.classpath
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/.project b/ch07/ch08/acl-example-from-scratch/.project
new file mode 100644
index 0000000..a72fa45
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.project
@@ -0,0 +1,42 @@
+
+
+ acl-example-from-scratch
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/.settings/.jsdtscope b/ch07/ch08/acl-example-from-scratch/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.jdt.core.prefs b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.m2e.core.prefs b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.common.component b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..c12f96c
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch07/ch08/acl-example-from-scratch/pom.xml b/ch07/ch08/acl-example-from-scratch/pom.xml
new file mode 100644
index 0000000..298851b
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/pom.xml
@@ -0,0 +1,113 @@
+
+ 4.0.0
+ com.apress.pss
+ acl-example-from-scratch
+ war
+ 1.0-SNAPSHOT
+ acl-example-from-scratch Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-taglibs
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-acl
+ 3.1.2.RELEASE
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+ org.aspectj
+ aspectjweaver
+ 1.7.0
+
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ javax.servlet.jsp
+ jsp-api
+ 2.1
+
+
+ javax.servlet
+ jstl
+ 1.2
+
+
+ javax.annotation
+ jsr250-api
+ 1.0
+
+
+ org.hsqldb
+ hsqldb
+ 2.2.8
+
+
+ net.sf.ehcache
+ ehcache-core
+ 2.6.0
+
+
+
+ acl-example-from-scratch
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/DatabaseSeeder.java b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/DatabaseSeeder.java
new file mode 100644
index 0000000..e776ade
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/DatabaseSeeder.java
@@ -0,0 +1,14 @@
+package com.apress.pss.acl;
+
+import java.io.IOException;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.util.FileCopyUtils;
+
+public class DatabaseSeeder {
+ public DatabaseSeeder(JdbcTemplate jdbcTemplate) throws IOException{
+ String sql = new String(FileCopyUtils.copyToByteArray(new ClassPathResource("customCreateAclSchema.sql").getInputStream()));
+ jdbcTemplate.execute(sql);
+ }
+}
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/controllers/ForumController.java b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/controllers/ForumController.java
new file mode 100644
index 0000000..9f8b11f
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/controllers/ForumController.java
@@ -0,0 +1,34 @@
+package com.apress.pss.acl.controllers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.apress.pss.acl.domain.Post;
+import com.apress.pss.acl.services.ForumService;
+
+@Controller
+@RequestMapping("/forum")
+public class ForumController {
+ @Autowired
+ private ForumService forumService;
+ @RequestMapping(method = RequestMethod.POST, value = "/post")
+ public ModelAndView createPost(@RequestBody String postContent){
+ forumService.createPost(new Post(postContent));
+ return showForm();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/")
+ public ModelAndView showForm(){
+ Map model = new HashMap();
+ model.put("posts", forumService.getPosts());
+ return new ModelAndView("form",model);
+ }
+}
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/domain/Post.java b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/domain/Post.java
new file mode 100644
index 0000000..3fdb99a
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/domain/Post.java
@@ -0,0 +1,56 @@
+package com.apress.pss.acl.domain;
+
+public class Post {
+
+ private String content;
+ private Integer id;
+
+ public Post(String postContent) {
+ this.content = postContent;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((content == null) ? 0 : content.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Post other = (Post) obj;
+ if (content == null) {
+ if (other.content != null)
+ return false;
+ } else if (!content.equals(other.content))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
+ }
+
+}
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/services/ForumService.java b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/services/ForumService.java
new file mode 100644
index 0000000..ada8416
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/services/ForumService.java
@@ -0,0 +1,10 @@
+package com.apress.pss.acl.services;
+
+import java.util.Map;
+
+import com.apress.pss.acl.domain.Post;
+
+public interface ForumService {
+ void createPost(Post post);
+ Map getPosts();
+}
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/services/ForumServiceImpl.java b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/services/ForumServiceImpl.java
new file mode 100644
index 0000000..75bbc54
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/java/com/apress/pss/acl/services/ForumServiceImpl.java
@@ -0,0 +1,56 @@
+package com.apress.pss.acl.services;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.annotation.Secured;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.GrantedAuthoritySid;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.security.core.userdetails.User;
+
+import com.apress.pss.acl.domain.Post;
+
+@Service
+public class ForumServiceImpl implements ForumService {
+ @Autowired
+ private MutableAclService mutableAclService;
+ private Map postStore = new HashMap();
+
+ @Transactional
+ @Secured({"ROLE_USER","ROLE_ADMIN"})
+ public void createPost(Post post) {
+ Integer id = new Integer(Math.abs(post.hashCode()));
+ ObjectIdentity oid = new ObjectIdentityImpl(Post.class, id);
+ MutableAcl acl = mutableAclService.createAcl(oid);
+
+ User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ acl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(
+ user.getUsername()), true);
+
+ acl.insertAce(1, BasePermission.DELETE, new GrantedAuthoritySid(
+ "ROLE_ADMIN"), true);
+ acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid(
+ "ROLE_USER"), true);
+ mutableAclService.updateAcl(acl);
+ post.setId(id);
+ postStore.put(id, post);
+ }
+
+ public Map getPosts(){
+ return postStore;
+ }
+
+ public void setMutableAclService(MutableAclService mutableAclService) {
+ this.mutableAclService = mutableAclService;
+ }
+
+}
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/resources/customCreateAclSchema.sql b/ch07/ch08/acl-example-from-scratch/src/main/resources/customCreateAclSchema.sql
new file mode 100644
index 0000000..d92404c
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/resources/customCreateAclSchema.sql
@@ -0,0 +1,40 @@
+
+
+create table acl_sid(
+ id bigint generated by default as identity(start with 100) not null primary key,
+ principal boolean not null,
+ sid varchar_ignorecase(100) not null,
+ constraint unique_uk_1 unique(sid,principal));
+
+create table acl_class(
+ id bigint generated by default as identity(start with 100) not null primary key,
+ class varchar_ignorecase(100) not null,
+ constraint unique_uk_2 unique(class)
+);
+
+create table acl_object_identity(
+ id bigint generated by default as identity(start with 100) not null primary key,
+ object_id_class bigint not null,
+ object_id_identity bigint not null,
+ parent_object bigint,
+ owner_sid bigint,
+ entries_inheriting boolean not null,
+ constraint unique_uk_3 unique(object_id_class,object_id_identity),
+ constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
+ constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
+ constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
+);
+
+create table acl_entry(
+ id bigint generated by default as identity(start with 100) not null primary key,
+ acl_object_identity bigint not null,
+ ace_order int not null,
+ sid bigint not null,
+ mask integer not null,
+ granting boolean not null,
+ audit_success boolean not null,
+ audit_failure boolean not null,
+ constraint unique_uk_4 unique(acl_object_identity,ace_order),
+ constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
+ constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
+);
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/acl-example-servlet.xml b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/acl-example-servlet.xml
new file mode 100644
index 0000000..8464e57
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/acl-example-servlet.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/applicationContext-acl.xml b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/applicationContext-acl.xml
new file mode 100644
index 0000000..6ff4433
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/applicationContext-acl.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..177b91b
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/views/form.jsp b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/views/form.jsp
new file mode 100644
index 0000000..e402907
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/views/form.jsp
@@ -0,0 +1,20 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib prefix="security"
+ uri="http://www.springframework.org/security/tags"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+
+Posts
+
+
+
+
+ ${posts[key].content}
+
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/web.xml b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ac1aec5
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,37 @@
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-acl.xml
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ acl-example
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ acl-example
+ /
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
diff --git a/ch07/ch08/acl-example-from-scratch/src/main/webapp/index.jsp b/ch07/ch08/acl-example-from-scratch/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch07/ch08/acl-example-from-scratch/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch07/ch08/acl-example/.classpath b/ch07/ch08/acl-example/.classpath
new file mode 100644
index 0000000..30daf94
--- /dev/null
+++ b/ch07/ch08/acl-example/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example/.project b/ch07/ch08/acl-example/.project
new file mode 100644
index 0000000..7d1a55f
--- /dev/null
+++ b/ch07/ch08/acl-example/.project
@@ -0,0 +1,48 @@
+
+
+ acl-example
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch07/ch08/acl-example/.settings/.jsdtscope b/ch07/ch08/acl-example/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch07/ch08/acl-example/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example/.settings/org.eclipse.jdt.core.prefs b/ch07/ch08/acl-example/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch07/ch08/acl-example/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch07/ch08/acl-example/.settings/org.eclipse.m2e.core.prefs b/ch07/ch08/acl-example/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch07/ch08/acl-example/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch07/ch08/acl-example/.settings/org.eclipse.wst.common.component b/ch07/ch08/acl-example/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..6e8d2de
--- /dev/null
+++ b/ch07/ch08/acl-example/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch07/ch08/acl-example/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch07/ch08/acl-example/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch07/ch08/acl-example/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch07/ch08/acl-example/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch07/ch08/acl-example/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch07/ch08/acl-example/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch07/ch08/acl-example/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch07/ch08/acl-example/aclexample.log b/ch07/ch08/acl-example/aclexample.log
new file mode 100644
index 0000000..996733e
--- /dev/null
+++ b/ch07/ch08/acl-example/aclexample.log
@@ -0,0 +1,12 @@
+/*C5*/SET SCHEMA PUBLIC
+-- ACL schema sql used in HSQLDB\u000a\u000adrop table acl_entry
+drop table acl_object_identity
+drop table acl_class
+drop table acl_sid
+create table acl_sid(\u000a id bigint generated by default as identity(start with 100) not null primary key,\u000a principal boolean not null,\u000a sid varchar_ignorecase(100) not null,\u000a constraint unique_uk_1 unique(sid,principal))
+create table acl_class(\u000a id bigint generated by default as identity(start with 100) not null primary key,\u000a class varchar_ignorecase(100) not null,\u000a constraint unique_uk_2 unique(class)\u000a)
+create table acl_object_identity(\u000a id bigint generated by default as identity(start with 100) not null primary key,\u000a object_id_class bigint not null,\u000a object_id_identity bigint not null,\u000a parent_object bigint,\u000a owner_sid bigint,\u000a entries_inheriting boolean not null,\u000a constraint unique_uk_3 unique(object_id_class,object_id_identity),\u000a constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),\u000a constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),\u000a constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)\u000a)
+create table acl_entry(\u000a id bigint generated by default as identity(start with 100) not null primary key,\u000a acl_object_identity bigint not null,\u000a ace_order int not null,\u000a sid bigint not null,\u000a mask integer not null,\u000a granting boolean not null,\u000a audit_success boolean not null,\u000a audit_failure boolean not null,\u000a constraint unique_uk_4 unique(acl_object_identity,ace_order),\u000a constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),\u000a constraint foreign_fk_5 foreign key(sid) references acl_sid(id)\u000a)
+DISCONNECT
+/*C6*/SET SCHEMA PUBLIC
+DISCONNECT
diff --git a/ch07/ch08/acl-example/aclexample.properties b/ch07/ch08/acl-example/aclexample.properties
new file mode 100644
index 0000000..d58e305
--- /dev/null
+++ b/ch07/ch08/acl-example/aclexample.properties
@@ -0,0 +1,4 @@
+#HSQL Database Engine 2.2.8
+#Wed Dec 05 21:44:26 GMT 2012
+version=2.2.8
+modified=yes
diff --git a/ch07/ch08/acl-example/aclexample.script b/ch07/ch08/acl-example/aclexample.script
new file mode 100644
index 0000000..30a00e0
--- /dev/null
+++ b/ch07/ch08/acl-example/aclexample.script
@@ -0,0 +1,63 @@
+SET DATABASE UNIQUE NAME HSQLDB3A6079489D
+SET DATABASE GC 0
+SET DATABASE DEFAULT RESULT MEMORY ROWS 0
+SET DATABASE EVENT LOG LEVEL 0
+SET DATABASE SQL NAMES FALSE
+SET DATABASE SQL REFERENCES FALSE
+SET DATABASE SQL SIZE TRUE
+SET DATABASE SQL TYPES FALSE
+SET DATABASE SQL TDC DELETE TRUE
+SET DATABASE SQL TDC UPDATE TRUE
+SET DATABASE SQL TRANSLATE TTI TYPES TRUE
+SET DATABASE SQL CONCAT NULLS TRUE
+SET DATABASE SQL NULLS FIRST TRUE
+SET DATABASE SQL UNIQUE NULLS TRUE
+SET DATABASE SQL CONVERT TRUNCATE TRUE
+SET DATABASE SQL AVG SCALE 0
+SET DATABASE SQL DOUBLE NAN TRUE
+SET DATABASE SQL LONGVAR IS LOB FALSE
+SET DATABASE TRANSACTION CONTROL LOCKS
+SET DATABASE DEFAULT ISOLATION LEVEL READ COMMITTED
+SET DATABASE TRANSACTION ROLLBACK ON CONFLICT TRUE
+SET DATABASE TEXT TABLE DEFAULTS ''
+SET FILES WRITE DELAY 500 MILLIS
+SET FILES BACKUP INCREMENT TRUE
+SET FILES CACHE SIZE 10000
+SET FILES CACHE ROWS 50000
+SET FILES SCALE 8
+SET FILES LOB SCALE 32
+SET FILES DEFRAG 0
+SET FILES NIO TRUE
+SET FILES NIO SIZE 256
+SET FILES LOG TRUE
+SET FILES LOG SIZE 50
+CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e'
+ALTER USER SA SET LOCAL TRUE
+CREATE SCHEMA PUBLIC AUTHORIZATION DBA
+SET SCHEMA PUBLIC
+CREATE MEMORY TABLE PUBLIC.ACL_SID(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,PRINCIPAL BOOLEAN NOT NULL,SID VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL))
+ALTER TABLE PUBLIC.ACL_SID ALTER COLUMN ID RESTART WITH 102
+CREATE MEMORY TABLE PUBLIC.ACL_CLASS(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,CLASS VARCHAR_IGNORECASE(100) NOT NULL,CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS))
+ALTER TABLE PUBLIC.ACL_CLASS ALTER COLUMN ID RESTART WITH 101
+CREATE MEMORY TABLE PUBLIC.ACL_OBJECT_IDENTITY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,OBJECT_ID_CLASS BIGINT NOT NULL,OBJECT_ID_IDENTITY BIGINT NOT NULL,PARENT_OBJECT BIGINT,OWNER_SID BIGINT,ENTRIES_INHERITING BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY),CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT) REFERENCES PUBLIC.ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS) REFERENCES PUBLIC.ACL_CLASS(ID),CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID) REFERENCES PUBLIC.ACL_SID(ID))
+ALTER TABLE PUBLIC.ACL_OBJECT_IDENTITY ALTER COLUMN ID RESTART WITH 101
+CREATE MEMORY TABLE PUBLIC.ACL_ENTRY(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY BIGINT NOT NULL,ACE_ORDER INTEGER NOT NULL,SID BIGINT NOT NULL,MASK INTEGER NOT NULL,GRANTING BOOLEAN NOT NULL,AUDIT_SUCCESS BOOLEAN NOT NULL,AUDIT_FAILURE BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER),CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES PUBLIC.ACL_OBJECT_IDENTITY(ID),CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES PUBLIC.ACL_SID(ID))
+ALTER TABLE PUBLIC.ACL_ENTRY ALTER COLUMN ID RESTART WITH 103
+ALTER SEQUENCE SYSTEM_LOBS.LOB_ID RESTART WITH 1
+SET DATABASE DEFAULT INITIAL SCHEMA PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.YES_OR_NO TO PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.TIME_STAMP TO PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CARDINAL_NUMBER TO PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CHARACTER_DATA TO PUBLIC
+GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.SQL_IDENTIFIER TO PUBLIC
+GRANT DBA TO SA
+SET SCHEMA SYSTEM_LOBS
+INSERT INTO BLOCKS VALUES(0,2147483647,0)
+SET SCHEMA PUBLIC
+INSERT INTO ACL_SID VALUES(100,TRUE,'mon')
+INSERT INTO ACL_SID VALUES(101,FALSE,'ROLE_ADMIN')
+INSERT INTO ACL_CLASS VALUES(100,'com.apress.pss.acl.domain.Post')
+INSERT INTO ACL_OBJECT_IDENTITY VALUES(100,100,749806588,NULL,100,TRUE)
+INSERT INTO ACL_ENTRY VALUES(100,100,0,100,16,TRUE,FALSE,FALSE)
+INSERT INTO ACL_ENTRY VALUES(101,100,1,101,8,TRUE,FALSE,FALSE)
+INSERT INTO ACL_ENTRY VALUES(102,100,2,101,1,TRUE,FALSE,FALSE)
diff --git a/ch07/ch08/acl-example/pom.xml b/ch07/ch08/acl-example/pom.xml
new file mode 100644
index 0000000..001ef44
--- /dev/null
+++ b/ch07/ch08/acl-example/pom.xml
@@ -0,0 +1,116 @@
+
+ 4.0.0
+ com.apress.pss
+ acl-example
+ war
+ 1.0.0-SNAPSHOT
+ Acl-example Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-taglibs
+ 3.1.2.RELEASE
+
+
+ org.springframework.security
+ spring-security-acl
+ 3.1.2.RELEASE
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+ org.aspectj
+ aspectjweaver
+ 1.7.0
+
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ javax.servlet.jsp
+ jsp-api
+ 2.1
+
+
+ javax.servlet
+ jstl
+ 1.2
+
+
+ javax.annotation
+ jsr250-api
+ 1.0
+
+
+ org.hsqldb
+ hsqldb
+ 2.2.8
+
+
+ net.sf.ehcache
+ ehcache-core
+ 2.6.0
+
+
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ acl-example
+
+
diff --git a/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/DatabaseSeeder.java b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/DatabaseSeeder.java
new file mode 100644
index 0000000..8245b1a
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/DatabaseSeeder.java
@@ -0,0 +1,14 @@
+package com.apress.pss.acl;
+
+import java.io.IOException;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.util.FileCopyUtils;
+
+public class DatabaseSeeder {
+ public DatabaseSeeder(JdbcTemplate jdbcTemplate) throws IOException{
+ String sql = new String(FileCopyUtils.copyToByteArray(new ClassPathResource("customCreateAclSchema.sql").getInputStream()));
+ jdbcTemplate.execute(sql);
+ }
+}
diff --git a/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/controllers/ForumController.java b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/controllers/ForumController.java
new file mode 100644
index 0000000..c2fe44c
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/controllers/ForumController.java
@@ -0,0 +1,42 @@
+package com.apress.pss.acl.controllers;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.apress.pss.acl.domain.Post;
+import com.apress.pss.acl.services.ForumService;
+
+@Controller
+@RequestMapping("/forum")
+public class ForumController {
+ @Autowired
+ private ForumService forumService;
+ @RequestMapping(method = RequestMethod.POST, value = "/post")
+ public ModelAndView createPost(@RequestBody String postContent){
+ forumService.createPost(new Post(postContent));
+ return showForm();
+ }
+
+ @RequestMapping(method = RequestMethod.POST, value = "/post/delete")
+ public ModelAndView deletePost(@RequestParam Integer postId){
+ Post post = new Post("non-relevant");
+ post.setId(postId);
+ forumService.deletePost(post);
+ return showForm();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/")
+ public ModelAndView showForm(){
+ Map model = new HashMap();
+ model.put("posts", forumService.getPosts());
+ return new ModelAndView("form",model);
+ }
+}
diff --git a/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/domain/Post.java b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/domain/Post.java
new file mode 100644
index 0000000..3fdb99a
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/domain/Post.java
@@ -0,0 +1,56 @@
+package com.apress.pss.acl.domain;
+
+public class Post {
+
+ private String content;
+ private Integer id;
+
+ public Post(String postContent) {
+ this.content = postContent;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((content == null) ? 0 : content.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Post other = (Post) obj;
+ if (content == null) {
+ if (other.content != null)
+ return false;
+ } else if (!content.equals(other.content))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
+ }
+
+}
diff --git a/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/services/ForumService.java b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/services/ForumService.java
new file mode 100644
index 0000000..a2fd75d
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/services/ForumService.java
@@ -0,0 +1,13 @@
+package com.apress.pss.acl.services;
+
+import java.util.Collection;
+
+import com.apress.pss.acl.domain.Post;
+
+public interface ForumService {
+ void createPost(Post post);
+
+ public abstract Collection getPosts();
+
+ public abstract void deletePost(Post post);
+}
diff --git a/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/services/ForumServiceImpl.java b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/services/ForumServiceImpl.java
new file mode 100644
index 0000000..f4a6a29
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/java/com/apress/pss/acl/services/ForumServiceImpl.java
@@ -0,0 +1,81 @@
+package com.apress.pss.acl.services;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.annotation.Secured;
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.GrantedAuthoritySid;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.apress.pss.acl.domain.Post;
+
+@Service
+public class ForumServiceImpl implements ForumService {
+ @Autowired
+ private MutableAclService mutableAclService;
+ private Map postStore = new HashMap();
+
+ @Transactional
+ public void createPost(Post post) {
+ Integer id = new Integer(Math.abs(post.hashCode()));
+ ObjectIdentity oid = new ObjectIdentityImpl(Post.class, id);
+ MutableAcl acl = mutableAclService.createAcl(oid);
+ User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+ acl.insertAce(0, BasePermission.ADMINISTRATION, new PrincipalSid(
+ user.getUsername()), true);
+ acl.insertAce(1, BasePermission.DELETE, new GrantedAuthoritySid(
+ "ROLE_ADMIN"), true);
+ if(isAdminUserLogged()){
+ acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid(
+ "ROLE_ADMIN"), true);
+ }else{
+ acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid(
+ "ROLE_USER"), true);
+ }
+ mutableAclService.updateAcl(acl);
+ post.setId(id);
+ postStore.put(id, post);
+ }
+
+
+ @Transactional
+ @Secured("ACL_POST_DELETE")
+ public void deletePost(Post post){
+ ObjectIdentity oid = new ObjectIdentityImpl(Post.class, post.getId());
+ mutableAclService.deleteAcl(oid, true);
+ postStore.remove(postStore.get(post.getId()));
+ }
+
+ //@PostFilter("hasPermission(filterObject, 'READ')")
+ public Collection getPosts(){
+ return new ArrayList(postStore.values());
+ }
+
+ public void setMutableAclService(MutableAclService mutableAclService) {
+ this.mutableAclService = mutableAclService;
+ }
+
+ private boolean isAdminUserLogged() {
+ for(GrantedAuthority authority: SecurityContextHolder.getContext().getAuthentication().getAuthorities()){
+ if(authority.getAuthority().equals("ROLE_ADMIN")){
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/ch07/ch08/acl-example/src/main/resources/customCreateAclSchema.sql b/ch07/ch08/acl-example/src/main/resources/customCreateAclSchema.sql
new file mode 100644
index 0000000..1ca98b1
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/resources/customCreateAclSchema.sql
@@ -0,0 +1,46 @@
+-- ACL schema sql used in HSQLDB
+
+drop table acl_entry;
+drop table acl_object_identity;
+drop table acl_class;
+drop table acl_sid;
+
+
+create table acl_sid(
+ id bigint generated by default as identity(start with 100) not null primary key,
+ principal boolean not null,
+ sid varchar_ignorecase(100) not null,
+ constraint unique_uk_1 unique(sid,principal));
+
+create table acl_class(
+ id bigint generated by default as identity(start with 100) not null primary key,
+ class varchar_ignorecase(100) not null,
+ constraint unique_uk_2 unique(class)
+);
+
+create table acl_object_identity(
+ id bigint generated by default as identity(start with 100) not null primary key,
+ object_id_class bigint not null,
+ object_id_identity bigint not null,
+ parent_object bigint,
+ owner_sid bigint,
+ entries_inheriting boolean not null,
+ constraint unique_uk_3 unique(object_id_class,object_id_identity),
+ constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
+ constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
+ constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
+);
+
+create table acl_entry(
+ id bigint generated by default as identity(start with 100) not null primary key,
+ acl_object_identity bigint not null,
+ ace_order int not null,
+ sid bigint not null,
+ mask integer not null,
+ granting boolean not null,
+ audit_success boolean not null,
+ audit_failure boolean not null,
+ constraint unique_uk_4 unique(acl_object_identity,ace_order),
+ constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
+ constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
+);
diff --git a/ch07/ch08/acl-example/src/main/webapp/WEB-INF/acl-example-servlet.xml b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/acl-example-servlet.xml
new file mode 100644
index 0000000..6732508
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/acl-example-servlet.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch07/ch08/acl-example/src/main/webapp/WEB-INF/applicationContext-acl.xml b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/applicationContext-acl.xml
new file mode 100644
index 0000000..44546fa
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/applicationContext-acl.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch07/ch08/acl-example/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..36c4da2
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch07/ch08/acl-example/src/main/webapp/WEB-INF/views/form.jsp b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/views/form.jsp
new file mode 100644
index 0000000..6695ac4
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/views/form.jsp
@@ -0,0 +1,26 @@
+<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
+ pageEncoding="ISO-8859-1"%>
+<%@ taglib prefix="security"
+ uri="http://www.springframework.org/security/tags"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+
+
+Posts
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch07/ch08/acl-example/src/main/webapp/WEB-INF/web.xml b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..6b72bd3
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,39 @@
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-acl.xml
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ acl-example
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ acl-example
+ /
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
+
+
diff --git a/ch07/ch08/acl-example/src/main/webapp/index.jsp b/ch07/ch08/acl-example/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch07/ch08/acl-example/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch08/ch09/.DS_Store b/ch08/ch09/.DS_Store
new file mode 100644
index 0000000..036a2c1
Binary files /dev/null and b/ch08/ch09/.DS_Store differ
diff --git a/ch08/ch09/example-custom-filter/.classpath b/ch08/ch09/example-custom-filter/.classpath
new file mode 100644
index 0000000..f9479ba
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example-custom-filter/.project b/ch08/ch09/example-custom-filter/.project
new file mode 100644
index 0000000..ef5ae8e
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/.project
@@ -0,0 +1,35 @@
+
+
+ ex-filter
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+
+
diff --git a/ch08/ch09/example-custom-filter/.settings/org.eclipse.jdt.core.prefs b/ch08/ch09/example-custom-filter/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..abec6ca
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch08/ch09/example-custom-filter/.settings/org.eclipse.m2e.core.prefs b/ch08/ch09/example-custom-filter/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch08/ch09/example-custom-filter/pom.xml b/ch08/ch09/example-custom-filter/pom.xml
new file mode 100644
index 0000000..1bc4126
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/pom.xml
@@ -0,0 +1,67 @@
+
+ 4.0.0
+ com.apress.pss
+ ex-filter
+ war
+ 1.0-SNAPSHOT
+ example filter Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch08/ch09/example-custom-filter/src/main/java/com/apress/pss/security/UserAgentFilter.java b/ch08/ch09/example-custom-filter/src/main/java/com/apress/pss/security/UserAgentFilter.java
new file mode 100644
index 0000000..b106b75
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/src/main/java/com/apress/pss/security/UserAgentFilter.java
@@ -0,0 +1,57 @@
+package com.apress.pss.security;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.authentication.AuthenticationTrustResolver;
+import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.GenericFilterBean;
+
+public class UserAgentFilter extends GenericFilterBean{
+
+ private static final String ADMIN_ROLE = "ROLE_ADMIN";
+ private static final String FIREFOX_AGENT_CONTAINS = "Firefox";
+ private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
+
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+ if(((HttpServletRequest)request).getHeader("User-Agent").contains(FIREFOX_AGENT_CONTAINS)){
+ chain.doFilter(request, response);
+ }else{
+ processRequestWhenNotExpectedUserAgent(request,response,chain);
+ }
+ }
+
+ private void processRequestWhenNotExpectedUserAgent(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+ if(isUserAnAdmin() || isUserAnonymous()){
+ chain.doFilter(request, response);
+ }else{
+ throw new AccessDeniedException("The browser you are using is not supported for your user role. Use Firefox instead");
+ }
+ }
+
+ private boolean isUserAnonymous() {
+ return SecurityContextHolder.getContext().getAuthentication() != null && authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication());
+ }
+
+ private boolean isUserAnAdmin() {
+ if(SecurityContextHolder.getContext().getAuthentication() != null){
+ for(GrantedAuthority ga : SecurityContextHolder.getContext().getAuthentication().getAuthorities()){
+ if(ga.getAuthority().equals(ADMIN_ROLE)){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/ch08/ch09/example-custom-filter/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch08/ch09/example-custom-filter/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch08/ch09/example-custom-filter/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch08/ch09/example-custom-filter/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..84a2733
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example-custom-filter/src/main/webapp/WEB-INF/web.xml b/ch08/ch09/example-custom-filter/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch08/ch09/example-custom-filter/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example-events/.classpath b/ch08/ch09/example-events/.classpath
new file mode 100644
index 0000000..f9479ba
--- /dev/null
+++ b/ch08/ch09/example-events/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example-events/.project b/ch08/ch09/example-events/.project
new file mode 100644
index 0000000..e2c16b2
--- /dev/null
+++ b/ch08/ch09/example-events/.project
@@ -0,0 +1,48 @@
+
+
+ pss01
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch08/ch09/example-events/.settings/.jsdtscope b/ch08/ch09/example-events/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch08/ch09/example-events/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example-events/.settings/org.eclipse.jdt.core.prefs b/ch08/ch09/example-events/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch08/ch09/example-events/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch08/ch09/example-events/.settings/org.eclipse.m2e.core.prefs b/ch08/ch09/example-events/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch08/ch09/example-events/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch08/ch09/example-events/.settings/org.eclipse.wst.common.component b/ch08/ch09/example-events/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..0f0acc4
--- /dev/null
+++ b/ch08/ch09/example-events/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch08/ch09/example-events/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch08/ch09/example-events/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..ef27789
--- /dev/null
+++ b/ch08/ch09/example-events/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example-events/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch08/ch09/example-events/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch08/ch09/example-events/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch08/ch09/example-events/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch08/ch09/example-events/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch08/ch09/example-events/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch08/ch09/example-events/pom.xml b/ch08/ch09/example-events/pom.xml
new file mode 100644
index 0000000..94e4067
--- /dev/null
+++ b/ch08/ch09/example-events/pom.xml
@@ -0,0 +1,72 @@
+
+ 4.0.0
+ com.apress.pss
+ exm-events
+ war
+ 1.0-SNAPSHOT
+ example Events Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ org.springframework.data
+ spring-data-mongodb
+ 1.0.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch08/ch09/example-events/src/main/java/com/apress/pss/UserInserter.java b/ch08/ch09/example-events/src/main/java/com/apress/pss/UserInserter.java
new file mode 100644
index 0000000..e3b6dde
--- /dev/null
+++ b/ch08/ch09/example-events/src/main/java/com/apress/pss/UserInserter.java
@@ -0,0 +1,24 @@
+package com.apress.pss;
+
+import java.util.Arrays;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.security.authentication.encoding.PasswordEncoder;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.provisioning.UserDetailsManager;
+
+public class UserInserter {
+ public static void main(String[] args){
+ ApplicationContext context = new FileSystemXmlApplicationContext("//Users/cscarioni/projects/pro-spring-security/src/ch09/example1/src/main/webapp/WEB-INF/applicationContext-security.xml");
+ UserDetailsManager userDetailsManager = context.getBean(UserDetailsManager.class);
+ GrantedAuthority[] authorities = new GrantedAuthority[] {new SimpleGrantedAuthority("ROLE_SCARVAREZ_MEMBER")};
+ PasswordEncoder encoder = context.getBean(PasswordEncoder.class);
+ UserDetails user = new User("car", encoder.encodePassword("scarvarez",null), Arrays.asList(authorities));
+ userDetailsManager.createUser(user);
+ }
+}
+
diff --git a/ch08/ch09/example-events/src/main/java/com/apress/pss/security/LoggerBadCredentialsEvents.java b/ch08/ch09/example-events/src/main/java/com/apress/pss/security/LoggerBadCredentialsEvents.java
new file mode 100644
index 0000000..45ecaec
--- /dev/null
+++ b/ch08/ch09/example-events/src/main/java/com/apress/pss/security/LoggerBadCredentialsEvents.java
@@ -0,0 +1,18 @@
+package com.apress.pss.security;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.ApplicationListener;
+import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
+
+public class LoggerBadCredentialsEvents implements ApplicationListener{
+
+ private static Log LOG = LogFactory.getLog(LoggerBadCredentialsEvents.class);
+ public void onApplicationEvent(
+ AuthenticationFailureBadCredentialsEvent event) {
+ LOG.warn("An attempt to login with bad credentials was made with username "+event.getAuthentication().getName());
+
+ }
+
+}
diff --git a/ch08/ch09/example-events/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch08/ch09/example-events/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch08/ch09/example-events/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch08/ch09/example-events/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch08/ch09/example-events/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..76fcba1
--- /dev/null
+++ b/ch08/ch09/example-events/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example-events/src/main/webapp/WEB-INF/web.xml b/ch08/ch09/example-events/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch08/ch09/example-events/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example-exceptions/.classpath b/ch08/ch09/example-exceptions/.classpath
new file mode 100644
index 0000000..f9479ba
--- /dev/null
+++ b/ch08/ch09/example-exceptions/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example-exceptions/.project b/ch08/ch09/example-exceptions/.project
new file mode 100644
index 0000000..0c541d2
--- /dev/null
+++ b/ch08/ch09/example-exceptions/.project
@@ -0,0 +1,35 @@
+
+
+ ex-filter
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+
+
diff --git a/ch08/ch09/example-exceptions/.settings/org.eclipse.jdt.core.prefs b/ch08/ch09/example-exceptions/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..abec6ca
--- /dev/null
+++ b/ch08/ch09/example-exceptions/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch08/ch09/example-exceptions/.settings/org.eclipse.m2e.core.prefs b/ch08/ch09/example-exceptions/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch08/ch09/example-exceptions/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch08/ch09/example-exceptions/pom.xml b/ch08/ch09/example-exceptions/pom.xml
new file mode 100644
index 0000000..1874e86
--- /dev/null
+++ b/ch08/ch09/example-exceptions/pom.xml
@@ -0,0 +1,67 @@
+
+ 4.0.0
+ com.apress.pss
+ ex-exceptions
+ war
+ 1.0-SNAPSHOT
+ example exception Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/AttemptsAuthenticationEntryPoint.java b/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/AttemptsAuthenticationEntryPoint.java
new file mode 100644
index 0000000..7f76ea5
--- /dev/null
+++ b/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/AttemptsAuthenticationEntryPoint.java
@@ -0,0 +1,33 @@
+package com.apress.pss.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+
+public class AttemptsAuthenticationEntryPoint implements AuthenticationEntryPoint{
+
+ public void commence(HttpServletRequest request,
+ HttpServletResponse response, AuthenticationException authException)
+ throws IOException, ServletException {
+ response.addHeader("WWW-Authenticate", "Basic realm=\"theapp\"");
+ response.addHeader("Set-Cookie", "authentication_attempts="+(getDeniesCookie(request)+1)+"; Max-Age=3600; Version=1");
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
+
+ }
+
+ private int getDeniesCookie(HttpServletRequest request) {
+ for(Cookie cookie:request.getCookies()){
+ if(cookie.getName().equals("authentication_attempts")){
+ return Integer.parseInt(cookie.getValue());
+ }
+ }
+ return 0;
+ }
+
+}
diff --git a/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/CookieAccessDeniedHandler.java b/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/CookieAccessDeniedHandler.java
new file mode 100644
index 0000000..a1854ff
--- /dev/null
+++ b/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/CookieAccessDeniedHandler.java
@@ -0,0 +1,48 @@
+package com.apress.pss.security;
+
+import java.io.IOException;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.WebAttributes;
+import org.springframework.security.web.access.AccessDeniedHandler;
+
+public class CookieAccessDeniedHandler implements AccessDeniedHandler {
+
+ private static final String ACCESS_DENIES = "access_denies";
+
+ private String errorPage;
+
+ public void handle(HttpServletRequest request,
+ HttpServletResponse response,
+ AccessDeniedException accessDeniedException) throws IOException,
+ ServletException {
+ if (!response.isCommitted()) {
+ response.addCookie(new Cookie(ACCESS_DENIES, String.valueOf(getDeniesCookie(request)+1)));
+ if (errorPage != null) {
+ request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException);
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage);
+ dispatcher.forward(request, response);
+ } else {
+ response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
+ }
+ }
+
+ }
+
+ private int getDeniesCookie(HttpServletRequest request) {
+ for(Cookie cookie:request.getCookies()){
+ if(cookie.getName().equals(ACCESS_DENIES)){
+ return Integer.parseInt(cookie.getValue());
+ }
+ }
+ return 0;
+ }
+
+}
diff --git a/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/URLAccessDecisionManager.java b/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/URLAccessDecisionManager.java
new file mode 100644
index 0000000..8cda538
--- /dev/null
+++ b/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/security/URLAccessDecisionManager.java
@@ -0,0 +1,40 @@
+package com.apress.pss.security;
+
+import java.util.Collection;
+
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.web.FilterInvocation;
+
+public class URLAccessDecisionManager implements AccessDecisionManager{
+
+ public void decide(Authentication authentication, Object object,
+ Collection configAttributes)
+ throws AccessDeniedException, InsufficientAuthenticationException {
+ FilterInvocation invocation = (FilterInvocation)object;
+ String url = invocation.getRequestUrl().replaceAll("/", "");
+ boolean granted = false;
+ for(GrantedAuthority authority:authentication.getAuthorities()){
+ if (authority.getAuthority().equals(url)){
+ granted = true;
+ break;
+ }
+ }
+ if(!granted){
+ throw new AccessDeniedException("Access denied");
+ }
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ return true;
+ }
+
+ public boolean supports(Class> clazz) {
+ return true;
+ }
+
+}
diff --git a/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch08/ch09/example-exceptions/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch08/ch09/example-exceptions/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch08/ch09/example-exceptions/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..d53a8ef
--- /dev/null
+++ b/ch08/ch09/example-exceptions/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example-exceptions/src/main/webapp/WEB-INF/web.xml b/ch08/ch09/example-exceptions/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch08/ch09/example-exceptions/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example-voters/.classpath b/ch08/ch09/example-voters/.classpath
new file mode 100644
index 0000000..f9479ba
--- /dev/null
+++ b/ch08/ch09/example-voters/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example-voters/.project b/ch08/ch09/example-voters/.project
new file mode 100644
index 0000000..84a65be
--- /dev/null
+++ b/ch08/ch09/example-voters/.project
@@ -0,0 +1,35 @@
+
+
+ ex-voters
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+
+
diff --git a/ch08/ch09/example-voters/.settings/org.eclipse.jdt.core.prefs b/ch08/ch09/example-voters/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..abec6ca
--- /dev/null
+++ b/ch08/ch09/example-voters/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch08/ch09/example-voters/.settings/org.eclipse.m2e.core.prefs b/ch08/ch09/example-voters/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch08/ch09/example-voters/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch08/ch09/example-voters/pom.xml b/ch08/ch09/example-voters/pom.xml
new file mode 100644
index 0000000..add7969
--- /dev/null
+++ b/ch08/ch09/example-voters/pom.xml
@@ -0,0 +1,67 @@
+
+ 4.0.0
+ com.apress.pss
+ ex-voters
+ war
+ 1.0-SNAPSHOT
+ example voters Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch08/ch09/example-voters/src/main/java/com/apress/pss/security/UsernameVoter.java b/ch08/ch09/example-voters/src/main/java/com/apress/pss/security/UsernameVoter.java
new file mode 100644
index 0000000..bb84c1f
--- /dev/null
+++ b/ch08/ch09/example-voters/src/main/java/com/apress/pss/security/UsernameVoter.java
@@ -0,0 +1,42 @@
+package com.apress.pss.security;
+
+import java.util.Collection;
+
+import org.springframework.security.access.AccessDecisionVoter;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.core.Authentication;
+
+public class UsernameVoter implements AccessDecisionVoter {
+
+ public boolean supports(ConfigAttribute attribute) {
+ if ((attribute.getAttribute() != null)
+ && attribute.getAttribute().startsWith("USERNAME_")) {
+ return true;
+ } else {
+ return false;
+ }
+
+ }
+
+ public boolean supports(Class> clazz) {
+ return true;
+ }
+
+ public int vote(Authentication authentication, Object object,
+ Collection attributes) {
+ int result = ACCESS_ABSTAIN;
+ String username = authentication.getName();
+ for (ConfigAttribute attribute : attributes) {
+ if (this.supports(attribute)) {
+ result = ACCESS_DENIED;
+ String stringedAttribute = attribute.getAttribute();
+ String shortedAttribute = attribute.getAttribute().substring(stringedAttribute.indexOf("_")+1, stringedAttribute.length());
+ if (shortedAttribute.equalsIgnoreCase(username)) {
+ return ACCESS_GRANTED;
+ }
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/ch08/ch09/example-voters/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch08/ch09/example-voters/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch08/ch09/example-voters/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch08/ch09/example-voters/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch08/ch09/example-voters/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..ed01ab1
--- /dev/null
+++ b/ch08/ch09/example-voters/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example-voters/src/main/webapp/WEB-INF/web.xml b/ch08/ch09/example-voters/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch08/ch09/example-voters/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example1/.classpath b/ch08/ch09/example1/.classpath
new file mode 100644
index 0000000..f9479ba
--- /dev/null
+++ b/ch08/ch09/example1/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example1/.project b/ch08/ch09/example1/.project
new file mode 100644
index 0000000..25e7692
--- /dev/null
+++ b/ch08/ch09/example1/.project
@@ -0,0 +1,48 @@
+
+
+ pss01
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch08/ch09/example1/.settings/.jsdtscope b/ch08/ch09/example1/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch08/ch09/example1/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example1/.settings/org.eclipse.jdt.core.prefs b/ch08/ch09/example1/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch08/ch09/example1/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch08/ch09/example1/.settings/org.eclipse.m2e.core.prefs b/ch08/ch09/example1/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch08/ch09/example1/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch08/ch09/example1/.settings/org.eclipse.wst.common.component b/ch08/ch09/example1/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..0f0acc4
--- /dev/null
+++ b/ch08/ch09/example1/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+ uses
+
+
+
+
+
diff --git a/ch08/ch09/example1/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch08/ch09/example1/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..ef27789
--- /dev/null
+++ b/ch08/ch09/example1/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch08/ch09/example1/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch08/ch09/example1/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch08/ch09/example1/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch08/ch09/example1/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch08/ch09/example1/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch08/ch09/example1/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch08/ch09/example1/pom.xml b/ch08/ch09/example1/pom.xml
new file mode 100644
index 0000000..5f9fcc6
--- /dev/null
+++ b/ch08/ch09/example1/pom.xml
@@ -0,0 +1,72 @@
+
+ 4.0.0
+ com.apress.pss
+ exm1
+ war
+ 1.0-SNAPSHOT
+ example 1 Maven Webapp
+ http://maven.apache.org
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ org.springframework.data
+ spring-data-mongodb
+ 1.1.0.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ pss01
+
+
diff --git a/ch08/ch09/example1/src/main/java/com/apress/pss/UserInserter.java b/ch08/ch09/example1/src/main/java/com/apress/pss/UserInserter.java
new file mode 100644
index 0000000..e3b6dde
--- /dev/null
+++ b/ch08/ch09/example1/src/main/java/com/apress/pss/UserInserter.java
@@ -0,0 +1,24 @@
+package com.apress.pss;
+
+import java.util.Arrays;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.security.authentication.encoding.PasswordEncoder;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.provisioning.UserDetailsManager;
+
+public class UserInserter {
+ public static void main(String[] args){
+ ApplicationContext context = new FileSystemXmlApplicationContext("//Users/cscarioni/projects/pro-spring-security/src/ch09/example1/src/main/webapp/WEB-INF/applicationContext-security.xml");
+ UserDetailsManager userDetailsManager = context.getBean(UserDetailsManager.class);
+ GrantedAuthority[] authorities = new GrantedAuthority[] {new SimpleGrantedAuthority("ROLE_SCARVAREZ_MEMBER")};
+ PasswordEncoder encoder = context.getBean(PasswordEncoder.class);
+ UserDetails user = new User("car", encoder.encodePassword("scarvarez",null), Arrays.asList(authorities));
+ userDetailsManager.createUser(user);
+ }
+}
+
diff --git a/ch08/ch09/example1/src/main/java/com/apress/pss/security/MongoUserDetailsService.java b/ch08/ch09/example1/src/main/java/com/apress/pss/security/MongoUserDetailsService.java
new file mode 100644
index 0000000..f20683b
--- /dev/null
+++ b/ch08/ch09/example1/src/main/java/com/apress/pss/security/MongoUserDetailsService.java
@@ -0,0 +1,50 @@
+package com.apress.pss.security;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.provisioning.UserDetailsManager;
+
+public class MongoUserDetailsService implements UserDetailsManager {
+
+ private MongoTemplate mongoTemplate;
+
+ public MongoUserDetailsService(MongoTemplate mongoTemplate){
+ this.mongoTemplate = mongoTemplate;
+ }
+
+ public UserDetails loadUserByUsername(String username)
+ throws UsernameNotFoundException {
+ UserDetails user = mongoTemplate.findOne(new Query(Criteria.where("username").is(username)),
+ User.class, "users");
+ if (user == null){
+ throw new UsernameNotFoundException("Username "+username+ " not found.");
+ }
+ return user;
+ }
+
+ public void createUser(UserDetails user) {
+ mongoTemplate.insert(user, "users");
+
+ }
+
+ public void updateUser(UserDetails user) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void deleteUser(String username) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void changePassword(String oldPassword, String newPassword) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean userExists(String username) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/ch08/ch09/example1/src/main/java/com/apress/pss/security/UserReadConverter.java b/ch08/ch09/example1/src/main/java/com/apress/pss/security/UserReadConverter.java
new file mode 100644
index 0000000..d2b2045
--- /dev/null
+++ b/ch08/ch09/example1/src/main/java/com/apress/pss/security/UserReadConverter.java
@@ -0,0 +1,32 @@
+package com.apress.pss.security;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.DBObject;
+
+public class UserReadConverter implements Converter {
+
+ public User convert(DBObject source) {
+ return new User((String) source.get("username"),
+ (String) source.get("password"),
+ convertAuthoritiesReading(source));
+ }
+
+ private Collection extends GrantedAuthority> convertAuthoritiesReading(
+ DBObject source) {
+ List> stringAuthorities = (BasicDBList) source.get("authorities");
+ List authorities = new ArrayList();
+ for (Object stringAuth : stringAuthorities) {
+ authorities.add(new SimpleGrantedAuthority((String)stringAuth));
+ }
+ return authorities;
+ }
+}
\ No newline at end of file
diff --git a/ch08/ch09/example1/src/main/java/com/apress/pss/security/UserWriteConverter.java b/ch08/ch09/example1/src/main/java/com/apress/pss/security/UserWriteConverter.java
new file mode 100644
index 0000000..eecc232
--- /dev/null
+++ b/ch08/ch09/example1/src/main/java/com/apress/pss/security/UserWriteConverter.java
@@ -0,0 +1,30 @@
+package com.apress.pss.security;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+
+public class UserWriteConverter implements Converter {
+
+ public DBObject convert(User source) {
+ DBObject dbObject = new BasicDBObject();
+ dbObject.put("username", source.getUsername());
+ dbObject.put("password", source.getPassword());
+ dbObject.put("authorities", authortiesAsStringArray(source));
+ return dbObject;
+ }
+
+ private Object authortiesAsStringArray(User source) {
+ String[] authorities = new String[source.getAuthorities().size()];
+ int i = 0;
+ for(GrantedAuthority auth: source.getAuthorities()){
+ authorities[i]=auth.getAuthority();
+ i++;
+ }
+ return authorities;
+ }
+
+}
diff --git a/ch08/ch09/example1/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java b/ch08/ch09/example1/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
new file mode 100644
index 0000000..0fbf109
--- /dev/null
+++ b/ch08/ch09/example1/src/main/java/com/apress/pss/servlets/HelloWorldServlet.java
@@ -0,0 +1,22 @@
+package com.apress.pss.servlets;
+
+import java.io.IOException;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@WebServlet(urlPatterns={"/hello"})
+public class HelloWorldServlet extends HttpServlet {
+ private static final long serialVersionUID = 2218168052197231866L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response){
+ try {
+ response.getWriter().write("Hello World");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/ch08/ch09/example1/src/main/webapp/WEB-INF/applicationContext-mongodb.xml b/ch08/ch09/example1/src/main/webapp/WEB-INF/applicationContext-mongodb.xml
new file mode 100644
index 0000000..894e758
--- /dev/null
+++ b/ch08/ch09/example1/src/main/webapp/WEB-INF/applicationContext-mongodb.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example1/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch08/ch09/example1/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..ab4d29a
--- /dev/null
+++ b/ch08/ch09/example1/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch08/ch09/example1/src/main/webapp/WEB-INF/web.xml b/ch08/ch09/example1/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fe095e6
--- /dev/null
+++ b/ch08/ch09/example1/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/.classpath b/ch09/ch10/demo-grails/.classpath
new file mode 100644
index 0000000..7901053
--- /dev/null
+++ b/ch09/ch10/demo-grails/.classpath
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/cache.properties b/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/cache.properties
new file mode 100644
index 0000000..b6c8ed5
--- /dev/null
+++ b/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/cache.properties
@@ -0,0 +1 @@
+#Thu Mar 21 23:16:11 GMT 2013
diff --git a/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/cache.properties.lock b/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/cache.properties.lock
new file mode 100644
index 0000000..40fdece
--- /dev/null
+++ b/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/cache.properties.lock
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/fileSnapshots.bin b/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/fileSnapshots.bin
new file mode 100644
index 0000000..edc9ea8
Binary files /dev/null and b/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/fileSnapshots.bin differ
diff --git a/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/taskArtifacts.bin b/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/taskArtifacts.bin
new file mode 100644
index 0000000..26759c9
Binary files /dev/null and b/ch09/ch10/demo-grails/.gradle/1.0/taskArtifacts/taskArtifacts.bin differ
diff --git a/ch09/ch10/demo-grails/.project b/ch09/ch10/demo-grails/.project
new file mode 100644
index 0000000..4d4c35f
--- /dev/null
+++ b/ch09/ch10/demo-grails/.project
@@ -0,0 +1,32 @@
+
+
+ demo-grails
+
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ com.springsource.sts.grails.core.nature
+ org.eclipse.jdt.groovy.core.groovyNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.wst.common.project.facet.core.nature
+
+
+
+ .link_to_grails_plugins
+ 2
+ GRAILS_ROOT/2.0.4/projects/demo-grails/plugins
+
+
+
diff --git a/ch09/ch10/demo-grails/.settings/com.springsource.sts.grails.core.prefs b/ch09/ch10/demo-grails/.settings/com.springsource.sts.grails.core.prefs
new file mode 100644
index 0000000..a0532dc
--- /dev/null
+++ b/ch09/ch10/demo-grails/.settings/com.springsource.sts.grails.core.prefs
@@ -0,0 +1,3 @@
+com.springsource.sts.grails.core.com.springsource.sts.grails.core.install.name=grails 2.1.1
+com.springsource.sts.grails.core.use.default.install=false
+eclipse.preferences.version=1
diff --git a/ch09/ch10/demo-grails/.settings/org.codehaus.groovy.eclipse.preferences.prefs b/ch09/ch10/demo-grails/.settings/org.codehaus.groovy.eclipse.preferences.prefs
new file mode 100644
index 0000000..bf339c7
--- /dev/null
+++ b/ch09/ch10/demo-grails/.settings/org.codehaus.groovy.eclipse.preferences.prefs
@@ -0,0 +1,3 @@
+#Created by grails
+eclipse.preferences.version=1
+groovy.dont.generate.class.files=true
diff --git a/ch09/ch10/demo-grails/.settings/org.eclipse.core.resources.prefs b/ch09/ch10/demo-grails/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..c8c46d6
--- /dev/null
+++ b/ch09/ch10/demo-grails/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,26 @@
+eclipse.preferences.version=1
+encoding//.link_to_grails_plugins/jquery-1.8.0/grails-app/i18n=UTF-8
+encoding//.link_to_grails_plugins/jquery-1.8.0/grails-app/i18n/messages.properties=UTF-8
+encoding//.link_to_grails_plugins/resources-1.1.6/grails-app/i18n=UTF-8
+encoding//.link_to_grails_plugins/resources-1.1.6/grails-app/i18n/messages.properties=UTF-8
+encoding//.link_to_grails_plugins/spring-security-core-1.2.7.3/grails-app/i18n=UTF-8
+encoding//.link_to_grails_plugins/spring-security-core-1.2.7.3/grails-app/i18n/spring-security-core.properties=UTF-8
+encoding//.link_to_grails_plugins/spring-security-core-1.2.7.3/grails-app/i18n/spring-security-core_de.properties=UTF-8
+encoding//.link_to_grails_plugins/spring-security-core-1.2.7.3/grails-app/i18n/spring-security-core_fr.properties=UTF-8
+encoding//grails-app/i18n=UTF-8
+encoding//grails-app/i18n/messages.properties=UTF-8
+encoding//grails-app/i18n/messages_cs_CZ.properties=UTF-8
+encoding//grails-app/i18n/messages_da.properties=UTF-8
+encoding//grails-app/i18n/messages_de.properties=UTF-8
+encoding//grails-app/i18n/messages_es.properties=UTF-8
+encoding//grails-app/i18n/messages_fr.properties=UTF-8
+encoding//grails-app/i18n/messages_it.properties=UTF-8
+encoding//grails-app/i18n/messages_ja.properties=UTF-8
+encoding//grails-app/i18n/messages_nl.properties=UTF-8
+encoding//grails-app/i18n/messages_pl.properties=UTF-8
+encoding//grails-app/i18n/messages_pt_BR.properties=UTF-8
+encoding//grails-app/i18n/messages_pt_PT.properties=UTF-8
+encoding//grails-app/i18n/messages_ru.properties=UTF-8
+encoding//grails-app/i18n/messages_sv.properties=UTF-8
+encoding//grails-app/i18n/messages_th.properties=UTF-8
+encoding//grails-app/i18n/messages_zh_CN.properties=UTF-8
diff --git a/ch09/ch10/demo-grails/.settings/org.eclipse.jdt.groovy.core.prefs b/ch09/ch10/demo-grails/.settings/org.eclipse.jdt.groovy.core.prefs
new file mode 100644
index 0000000..a0aa4d4
--- /dev/null
+++ b/ch09/ch10/demo-grails/.settings/org.eclipse.jdt.groovy.core.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+groovy.compiler.level=20
diff --git a/ch09/ch10/demo-grails/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch09/ch10/demo-grails/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..13ac95c
--- /dev/null
+++ b/ch09/ch10/demo-grails/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/ch09/ch10/demo-grails/application.properties b/ch09/ch10/demo-grails/application.properties
new file mode 100644
index 0000000..0ffd7fd
--- /dev/null
+++ b/ch09/ch10/demo-grails/application.properties
@@ -0,0 +1,6 @@
+#Grails Metadata file
+#Mon Oct 08 21:22:39 BST 2012
+app.grails.version=2.1.1
+app.name=demo-grails
+app.version=0.1
+plugins.spring-security-core=1.2.7.3
diff --git a/ch09/ch10/demo-grails/grails-app/conf/ApplicationResources.groovy b/ch09/ch10/demo-grails/grails-app/conf/ApplicationResources.groovy
new file mode 100644
index 0000000..06b60c7
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/conf/ApplicationResources.groovy
@@ -0,0 +1,5 @@
+modules = {
+ application {
+ resource url:'js/application.js'
+ }
+}
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/grails-app/conf/BootStrap.groovy b/ch09/ch10/demo-grails/grails-app/conf/BootStrap.groovy
new file mode 100644
index 0000000..9cb9e14
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/conf/BootStrap.groovy
@@ -0,0 +1,22 @@
+import demo.security.Role
+import demo.security.User
+import demo.security.UserRole
+
+class BootStrap {
+
+ def init = { servletContext ->
+ def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
+ def userRole = new Role(authority: 'ROLE_USER').save(flush: true)
+
+ def testAdmin = new User(username: 'carlo', enabled: true, password: 'password')
+ testAdmin.save(flush: true)
+ def testUser = new User(username: 'monica', enabled: true, password: 'password')
+ testUser.save(flush: true)
+
+ UserRole.create testAdmin, adminRole, true
+ UserRole.create testUser, userRole, false
+
+ }
+ def destroy = {
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/conf/BuildConfig.groovy b/ch09/ch10/demo-grails/grails-app/conf/BuildConfig.groovy
new file mode 100644
index 0000000..41db690
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/conf/BuildConfig.groovy
@@ -0,0 +1,56 @@
+grails.servlet.version = "2.5" // Change depending on target container compliance (2.5 or 3.0)
+grails.project.class.dir = "target/classes"
+grails.project.test.class.dir = "target/test-classes"
+grails.project.test.reports.dir = "target/test-reports"
+grails.project.target.level = 1.6
+grails.project.source.level = 1.6
+//grails.project.war.file = "target/${appName}-${appVersion}.war"
+
+grails.project.dependency.resolution = {
+ // inherit Grails' default dependencies
+ inherits("global") {
+ // specify dependency exclusions here; for example, uncomment this to disable ehcache:
+ // excludes 'ehcache'
+ }
+ log "error" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
+ checksums true // Whether to verify checksums on resolve
+
+ repositories {
+ inherits true // Whether to inherit repository definitions from plugins
+
+ grailsPlugins()
+ grailsHome()
+ grailsCentral()
+
+ mavenLocal()
+ mavenCentral()
+
+ // uncomment these (or add new ones) to enable remote dependency resolution from public Maven repositories
+ //mavenRepo "http://snapshots.repository.codehaus.org"
+ //mavenRepo "http://repository.codehaus.org"
+ //mavenRepo "http://download.java.net/maven/2/"
+ //mavenRepo "http://repository.jboss.com/maven2/"
+ }
+ dependencies {
+ // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
+
+ // runtime 'mysql:mysql-connector-java:5.1.20'
+ }
+
+ plugins {
+ runtime ":hibernate:$grailsVersion"
+ runtime ":jquery:1.8.0"
+ runtime ":resources:1.1.6"
+
+ // Uncomment these (or add new ones) to enable additional resources capabilities
+ //runtime ":zipped-resources:1.0"
+ //runtime ":cached-resources:1.0"
+ //runtime ":yui-minify-resources:0.1.4"
+
+ build ":tomcat:$grailsVersion"
+
+ runtime ":database-migration:1.1"
+
+ compile ':cache:1.0.0'
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/conf/Config.groovy b/ch09/ch10/demo-grails/grails-app/conf/Config.groovy
new file mode 100644
index 0000000..67e7d27
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/conf/Config.groovy
@@ -0,0 +1,97 @@
+// locations to search for config files that get merged into the main config;
+// config files can be ConfigSlurper scripts, Java properties files, or classes
+// in the classpath in ConfigSlurper format
+
+// grails.config.locations = [ "classpath:${appName}-config.properties",
+// "classpath:${appName}-config.groovy",
+// "file:${userHome}/.grails/${appName}-config.properties",
+// "file:${userHome}/.grails/${appName}-config.groovy"]
+
+// if (System.properties["${appName}.config.location"]) {
+// grails.config.locations << "file:" + System.properties["${appName}.config.location"]
+// }
+
+grails.project.groupId = appName // change this to alter the default package name and Maven publishing destination
+grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
+grails.mime.use.accept.header = false
+grails.mime.types = [
+ all: '*/*',
+ atom: 'application/atom+xml',
+ css: 'text/css',
+ csv: 'text/csv',
+ form: 'application/x-www-form-urlencoded',
+ html: ['text/html','application/xhtml+xml'],
+ js: 'text/javascript',
+ json: ['application/json', 'text/json'],
+ multipartForm: 'multipart/form-data',
+ rss: 'application/rss+xml',
+ text: 'text/plain',
+ xml: ['text/xml', 'application/xml']
+]
+
+// URL Mapping Cache Max Size, defaults to 5000
+//grails.urlmapping.cache.maxsize = 1000
+
+// What URL patterns should be processed by the resources plugin
+grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*']
+
+// The default codec used to encode data with ${}
+grails.views.default.codec = "none" // none, html, base64
+grails.views.gsp.encoding = "UTF-8"
+grails.converters.encoding = "UTF-8"
+// enable Sitemesh preprocessing of GSP pages
+grails.views.gsp.sitemesh.preprocess = true
+// scaffolding templates configuration
+grails.scaffolding.templates.domainSuffix = 'Instance'
+
+// Set to false to use the new Grails 1.2 JSONBuilder in the render method
+grails.json.legacy.builder = false
+// enabled native2ascii conversion of i18n properties files
+grails.enable.native2ascii = true
+// packages to include in Spring bean scanning
+grails.spring.bean.packages = []
+// whether to disable processing of multi part requests
+grails.web.disable.multipart=false
+
+// request parameters to mask when logging exceptions
+grails.exceptionresolver.params.exclude = ['password']
+
+// configure auto-caching of queries by default (if false you can cache individual queries with 'cache: true')
+grails.hibernate.cache.queries = false
+
+environments {
+ development {
+ grails.logging.jul.usebridge = true
+ }
+ production {
+ grails.logging.jul.usebridge = false
+ // TODO: grails.serverURL = "http://www.changeme.com"
+ }
+}
+
+// log4j configuration
+log4j = {
+ // Example of changing the log pattern for the default console appender:
+ //
+ //appenders {
+ // console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
+ //}
+
+ error 'org.codehaus.groovy.grails.web.servlet', // controllers
+ 'org.codehaus.groovy.grails.web.pages', // GSP
+ 'org.codehaus.groovy.grails.web.sitemesh', // layouts
+ 'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
+ 'org.codehaus.groovy.grails.web.mapping', // URL mapping
+ 'org.codehaus.groovy.grails.commons', // core / classloading
+ 'org.codehaus.groovy.grails.plugins', // plugins
+ 'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
+ 'org.springframework',
+ 'org.hibernate',
+ 'net.sf.ehcache.hibernate'
+}
+
+// Added by the Spring Security Core plugin:
+grails.plugins.springsecurity.userLookup.userDomainClassName = 'demo.security.User'
+grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'demo.security.UserRole'
+grails.plugins.springsecurity.authority.className = 'demo.security.Role'
+grails.plugins.springsecurity.securityConfigType = "Annotation"
diff --git a/ch09/ch10/demo-grails/grails-app/conf/DataSource.groovy b/ch09/ch10/demo-grails/grails-app/conf/DataSource.groovy
new file mode 100644
index 0000000..afe0e6f
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/conf/DataSource.groovy
@@ -0,0 +1,43 @@
+dataSource {
+ pooled = true
+ driverClassName = "org.h2.Driver"
+ username = "sa"
+ password = ""
+}
+hibernate {
+ cache.use_second_level_cache = true
+ cache.use_query_cache = false
+ cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
+}
+// environment specific settings
+environments {
+ development {
+ dataSource {
+ dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
+ url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
+ }
+ }
+ test {
+ dataSource {
+ dbCreate = "update"
+ url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
+ }
+ }
+ production {
+ dataSource {
+ dbCreate = "update"
+ url = "jdbc:h2:prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
+ pooled = true
+ properties {
+ maxActive = -1
+ minEvictableIdleTimeMillis=1800000
+ timeBetweenEvictionRunsMillis=1800000
+ numTestsPerEvictionRun=3
+ testOnBorrow=true
+ testWhileIdle=true
+ testOnReturn=true
+ validationQuery="SELECT 1"
+ }
+ }
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/conf/UrlMappings.groovy b/ch09/ch10/demo-grails/grails-app/conf/UrlMappings.groovy
new file mode 100644
index 0000000..8c597d6
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/conf/UrlMappings.groovy
@@ -0,0 +1,13 @@
+class UrlMappings {
+
+ static mappings = {
+ "/$controller/$action?/$id?"{
+ constraints {
+ // apply constraints here
+ }
+ }
+
+ "/"(view:"/index")
+ "500"(view:'/error')
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/conf/spring/resources.groovy b/ch09/ch10/demo-grails/grails-app/conf/spring/resources.groovy
new file mode 100644
index 0000000..fa95006
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/conf/spring/resources.groovy
@@ -0,0 +1,3 @@
+// Place your Spring DSL code here
+beans = {
+}
diff --git a/ch09/ch10/demo-grails/grails-app/controllers/LoginController.groovy b/ch09/ch10/demo-grails/grails-app/controllers/LoginController.groovy
new file mode 100644
index 0000000..d380890
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/controllers/LoginController.groovy
@@ -0,0 +1,134 @@
+import grails.converters.JSON
+
+import javax.servlet.http.HttpServletResponse
+
+import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
+
+import org.springframework.security.authentication.AccountExpiredException
+import org.springframework.security.authentication.CredentialsExpiredException
+import org.springframework.security.authentication.DisabledException
+import org.springframework.security.authentication.LockedException
+import org.springframework.security.core.context.SecurityContextHolder as SCH
+import org.springframework.security.web.WebAttributes
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
+
+class LoginController {
+
+ /**
+ * Dependency injection for the authenticationTrustResolver.
+ */
+ def authenticationTrustResolver
+
+ /**
+ * Dependency injection for the springSecurityService.
+ */
+ def springSecurityService
+
+ /**
+ * Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise.
+ */
+ def index = {
+ if (springSecurityService.isLoggedIn()) {
+ redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
+ }
+ else {
+ redirect action: 'auth', params: params
+ }
+ }
+
+ /**
+ * Show the login page.
+ */
+ def auth = {
+
+ def config = SpringSecurityUtils.securityConfig
+
+ if (springSecurityService.isLoggedIn()) {
+ redirect uri: config.successHandler.defaultTargetUrl
+ return
+ }
+
+ String view = 'auth'
+ String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
+ render view: view, model: [postUrl: postUrl,
+ rememberMeParameter: config.rememberMe.parameter]
+ }
+
+ /**
+ * The redirect action for Ajax requests.
+ */
+ def authAjax = {
+ response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl
+ response.sendError HttpServletResponse.SC_UNAUTHORIZED
+ }
+
+ /**
+ * Show denied page.
+ */
+ def denied = {
+ if (springSecurityService.isLoggedIn() &&
+ authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
+ // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
+ redirect action: 'full', params: params
+ }
+ }
+
+ /**
+ * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
+ */
+ def full = {
+ def config = SpringSecurityUtils.securityConfig
+ render view: 'auth', params: params,
+ model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication),
+ postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"]
+ }
+
+ /**
+ * Callback after a failed login. Redirects to the auth page with a warning message.
+ */
+ def authfail = {
+
+ def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
+ String msg = ''
+ def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
+ if (exception) {
+ if (exception instanceof AccountExpiredException) {
+ msg = g.message(code: "springSecurity.errors.login.expired")
+ }
+ else if (exception instanceof CredentialsExpiredException) {
+ msg = g.message(code: "springSecurity.errors.login.passwordExpired")
+ }
+ else if (exception instanceof DisabledException) {
+ msg = g.message(code: "springSecurity.errors.login.disabled")
+ }
+ else if (exception instanceof LockedException) {
+ msg = g.message(code: "springSecurity.errors.login.locked")
+ }
+ else {
+ msg = g.message(code: "springSecurity.errors.login.fail")
+ }
+ }
+
+ if (springSecurityService.isAjax(request)) {
+ render([error: msg] as JSON)
+ }
+ else {
+ flash.message = msg
+ redirect action: 'auth', params: params
+ }
+ }
+
+ /**
+ * The Ajax success redirect url.
+ */
+ def ajaxSuccess = {
+ render([success: true, username: springSecurityService.authentication.name] as JSON)
+ }
+
+ /**
+ * The Ajax denied redirect url.
+ */
+ def ajaxDenied = {
+ render([error: 'access denied'] as JSON)
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/controllers/LogoutController.groovy b/ch09/ch10/demo-grails/grails-app/controllers/LogoutController.groovy
new file mode 100644
index 0000000..0f70860
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/controllers/LogoutController.groovy
@@ -0,0 +1,12 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
+
+class LogoutController {
+
+ /**
+ * Index action. Redirects to the Spring security logout uri.
+ */
+ def index = {
+ // TODO put any pre-logout code here
+ redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/controllers/demo/grails/SecuredController.groovy b/ch09/ch10/demo-grails/grails-app/controllers/demo/grails/SecuredController.groovy
new file mode 100644
index 0000000..8be0fdb
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/controllers/demo/grails/SecuredController.groovy
@@ -0,0 +1,11 @@
+package demo.grails
+
+import grails.plugins.springsecurity.Secured;
+
+class SecuredController {
+
+ @Secured(["ROLE_ADMIN"])
+ def message() {
+ render "Incredibly confidential message"
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/controllers/demo/grails/UnsecuredController.groovy b/ch09/ch10/demo-grails/grails-app/controllers/demo/grails/UnsecuredController.groovy
new file mode 100644
index 0000000..7aca187
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/controllers/demo/grails/UnsecuredController.groovy
@@ -0,0 +1,11 @@
+package demo.grails
+
+import grails.plugins.springsecurity.Secured;
+
+class UnsecuredController {
+
+ @Secured(["ROLE_USER"])
+ def message() {
+ render "message for everyone"
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/domain/demo/security/Role.groovy b/ch09/ch10/demo-grails/grails-app/domain/demo/security/Role.groovy
new file mode 100644
index 0000000..fd56569
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/domain/demo/security/Role.groovy
@@ -0,0 +1,14 @@
+package demo.security
+
+class Role {
+
+ String authority
+
+ static mapping = {
+ cache true
+ }
+
+ static constraints = {
+ authority blank: false, unique: true
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/domain/demo/security/User.groovy b/ch09/ch10/demo-grails/grails-app/domain/demo/security/User.groovy
new file mode 100644
index 0000000..02084b5
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/domain/demo/security/User.groovy
@@ -0,0 +1,40 @@
+package demo.security
+
+class User {
+
+ transient springSecurityService
+
+ String username
+ String password
+ boolean enabled
+ boolean accountExpired
+ boolean accountLocked
+ boolean passwordExpired
+
+ static constraints = {
+ username blank: false, unique: true
+ password blank: false
+ }
+
+ static mapping = {
+ password column: '`password`'
+ }
+
+ Set getAuthorities() {
+ UserRole.findAllByUser(this).collect { it.role } as Set
+ }
+
+ def beforeInsert() {
+ encodePassword()
+ }
+
+ def beforeUpdate() {
+ if (isDirty('password')) {
+ encodePassword()
+ }
+ }
+
+ protected void encodePassword() {
+ password = springSecurityService.encodePassword(password)
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/domain/demo/security/UserRole.groovy b/ch09/ch10/demo-grails/grails-app/domain/demo/security/UserRole.groovy
new file mode 100644
index 0000000..001f701
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/domain/demo/security/UserRole.groovy
@@ -0,0 +1,57 @@
+package demo.security
+
+import org.apache.commons.lang.builder.HashCodeBuilder
+
+class UserRole implements Serializable {
+
+ User user
+ Role role
+
+ boolean equals(other) {
+ if (!(other instanceof UserRole)) {
+ return false
+ }
+
+ other.user?.id == user?.id &&
+ other.role?.id == role?.id
+ }
+
+ int hashCode() {
+ def builder = new HashCodeBuilder()
+ if (user) builder.append(user.id)
+ if (role) builder.append(role.id)
+ builder.toHashCode()
+ }
+
+ static UserRole get(long userId, long roleId) {
+ find 'from UserRole where user.id=:userId and role.id=:roleId',
+ [userId: userId, roleId: roleId]
+ }
+
+ static UserRole create(User user, Role role, boolean flush = false) {
+ new UserRole(user: user, role: role).save(flush: flush, insert: true)
+ }
+
+ static boolean remove(User user, Role role, boolean flush = false) {
+ UserRole instance = UserRole.findByUserAndRole(user, role)
+ if (!instance) {
+ return false
+ }
+
+ instance.delete(flush: flush)
+ true
+ }
+
+ static void removeAll(User user) {
+ executeUpdate 'DELETE FROM UserRole WHERE user=:user', [user: user]
+ }
+
+ static void removeAll(Role role) {
+ executeUpdate 'DELETE FROM UserRole WHERE role=:role', [role: role]
+ }
+
+ static mapping = {
+ id composite: ['role', 'user']
+ version false
+ }
+}
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages.properties
new file mode 100644
index 0000000..0c9d7ee
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=Property [{0}] of class [{1}] with value [{2}] does not match the required pattern [{3}]
+default.invalid.url.message=Property [{0}] of class [{1}] with value [{2}] is not a valid URL
+default.invalid.creditCard.message=Property [{0}] of class [{1}] with value [{2}] is not a valid credit card number
+default.invalid.email.message=Property [{0}] of class [{1}] with value [{2}] is not a valid e-mail address
+default.invalid.range.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid range from [{3}] to [{4}]
+default.invalid.size.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid size range from [{3}] to [{4}]
+default.invalid.max.message=Property [{0}] of class [{1}] with value [{2}] exceeds maximum value [{3}]
+default.invalid.min.message=Property [{0}] of class [{1}] with value [{2}] is less than minimum value [{3}]
+default.invalid.max.size.message=Property [{0}] of class [{1}] with value [{2}] exceeds the maximum size of [{3}]
+default.invalid.min.size.message=Property [{0}] of class [{1}] with value [{2}] is less than the minimum size of [{3}]
+default.invalid.validator.message=Property [{0}] of class [{1}] with value [{2}] does not pass custom validation
+default.not.inlist.message=Property [{0}] of class [{1}] with value [{2}] is not contained within the list [{3}]
+default.blank.message=Property [{0}] of class [{1}] cannot be blank
+default.not.equal.message=Property [{0}] of class [{1}] with value [{2}] cannot equal [{3}]
+default.null.message=Property [{0}] of class [{1}] cannot be null
+default.not.unique.message=Property [{0}] of class [{1}] with value [{2}] must be unique
+
+default.paginate.prev=Previous
+default.paginate.next=Next
+default.boolean.true=True
+default.boolean.false=False
+default.date.format=yyyy-MM-dd HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} created
+default.updated.message={0} {1} updated
+default.deleted.message={0} {1} deleted
+default.not.deleted.message={0} {1} could not be deleted
+default.not.found.message={0} not found with id {1}
+default.optimistic.locking.failure=Another user has updated this {0} while you were editing
+
+default.home.label=Home
+default.list.label={0} List
+default.add.label=Add {0}
+default.new.label=New {0}
+default.create.label=Create {0}
+default.show.label=Show {0}
+default.edit.label=Edit {0}
+
+default.button.create.label=Create
+default.button.edit.label=Edit
+default.button.update.label=Update
+default.button.delete.label=Delete
+default.button.delete.confirm.message=Are you sure?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Property {0} must be a valid URL
+typeMismatch.java.net.URI=Property {0} must be a valid URI
+typeMismatch.java.util.Date=Property {0} must be a valid Date
+typeMismatch.java.lang.Double=Property {0} must be a valid number
+typeMismatch.java.lang.Integer=Property {0} must be a valid number
+typeMismatch.java.lang.Long=Property {0} must be a valid number
+typeMismatch.java.lang.Short=Property {0} must be a valid number
+typeMismatch.java.math.BigDecimal=Property {0} must be a valid number
+typeMismatch.java.math.BigInteger=Property {0} must be a valid number
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_cs_CZ.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_cs_CZ.properties
new file mode 100644
index 0000000..ab45c43
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_cs_CZ.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] neodpovídá požadovanému vzoru [{3}]
+default.invalid.url.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní URL
+default.invalid.creditCard.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní číslo kreditní karty
+default.invalid.email.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není validní emailová adresa
+default.invalid.range.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není v povoleném rozmezí od [{3}] do [{4}]
+default.invalid.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není v povoleném rozmezí od [{3}] do [{4}]
+default.invalid.max.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] překračuje maximální povolenou hodnotu [{3}]
+default.invalid.min.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] je menší než minimální povolená hodnota [{3}]
+default.invalid.max.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] překračuje maximální velikost [{3}]
+default.invalid.min.size.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] je menší než minimální velikost [{3}]
+default.invalid.validator.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] neprošla validací
+default.not.inlist.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] není obsažena v seznamu [{3}]
+default.blank.message=Položka [{0}] třídy [{1}] nemůže být prázdná
+default.not.equal.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] nemůže být stejná jako [{3}]
+default.null.message=Položka [{0}] třídy [{1}] nemůže být prázdná
+default.not.unique.message=Položka [{0}] třídy [{1}] o hodnotě [{2}] musí být unikátní
+
+default.paginate.prev=Předcházející
+default.paginate.next=Následující
+default.boolean.true=Pravda
+default.boolean.false=Nepravda
+default.date.format=dd. MM. yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} vytvořeno
+default.updated.message={0} {1} aktualizováno
+default.deleted.message={0} {1} smazáno
+default.not.deleted.message={0} {1} nelze smazat
+default.not.found.message={0} nenalezen s id {1}
+default.optimistic.locking.failure=Jiný uživatel aktualizoval záznam {0}, právě když byl vámi editován
+
+default.home.label=Domů
+default.list.label={0} Seznam
+default.add.label=Přidat {0}
+default.new.label=Nový {0}
+default.create.label=Vytvořit {0}
+default.show.label=Ukázat {0}
+default.edit.label=Editovat {0}
+
+default.button.create.label=Vytvoř
+default.button.edit.label=Edituj
+default.button.update.label=Aktualizuj
+default.button.delete.label=Smaž
+default.button.delete.confirm.message=Jste si jistý?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Položka {0} musí být validní URL
+typeMismatch.java.net.URI=Položka {0} musí být validní URI
+typeMismatch.java.util.Date=Položka {0} musí být validní datum
+typeMismatch.java.lang.Double=Položka {0} musí být validní desetinné číslo
+typeMismatch.java.lang.Integer=Položka {0} musí být validní číslo
+typeMismatch.java.lang.Long=Položka {0} musí být validní číslo
+typeMismatch.java.lang.Short=Položka {0} musí být validní číslo
+typeMismatch.java.math.BigDecimal=Položka {0} musí být validní číslo
+typeMismatch.java.math.BigInteger=Položka {0} musí být validní číslo
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_da.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_da.properties
new file mode 100644
index 0000000..858b229
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_da.properties
@@ -0,0 +1,56 @@
+default.doesnt.match.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] overholder ikke mønsteret [{3}]
+default.invalid.url.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] er ikke en gyldig URL
+default.invalid.creditCard.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] er ikke et gyldigt kreditkortnummer
+default.invalid.email.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] er ikke en gyldig e-mail adresse
+default.invalid.range.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] ligger ikke inden for intervallet fra [{3}] til [{4}]
+default.invalid.size.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] ligger ikke inden for størrelsen fra [{3}] til [{4}]
+default.invalid.max.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] overstiger den maksimale værdi [{3}]
+default.invalid.min.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] er under den minimale værdi [{3}]
+default.invalid.max.size.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] overstiger den maksimale størrelse på [{3}]
+default.invalid.min.size.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] er under den minimale størrelse på [{3}]
+default.invalid.validator.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] overholder ikke den brugerdefinerede validering
+default.not.inlist.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] findes ikke i listen [{3}]
+default.blank.message=Feltet [{0}] i klassen [{1}] kan ikke være tom
+default.not.equal.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] må ikke være [{3}]
+default.null.message=Feltet [{0}] i klassen [{1}] kan ikke være null
+default.not.unique.message=Feltet [{0}] i klassen [{1}] som har værdien [{2}] skal være unik
+
+default.paginate.prev=Forrige
+default.paginate.next=Næste
+default.boolean.true=Sand
+default.boolean.false=Falsk
+default.date.format=yyyy-MM-dd HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} oprettet
+default.updated.message={0} {1} opdateret
+default.deleted.message={0} {1} slettet
+default.not.deleted.message={0} {1} kunne ikke slettes
+default.not.found.message={0} med id {1} er ikke fundet
+default.optimistic.locking.failure=En anden bruger har opdateret denne {0} imens du har lavet rettelser
+
+default.home.label=Hjem
+default.list.label={0} Liste
+default.add.label=Tilføj {0}
+default.new.label=Ny {0}
+default.create.label=Opret {0}
+default.show.label=Vis {0}
+default.edit.label=Ret {0}
+
+default.button.create.label=Opret
+default.button.edit.label=Ret
+default.button.update.label=Opdater
+default.button.delete.label=Slet
+default.button.delete.confirm.message=Er du sikker?
+
+# Databindingsfejl. Brug "typeMismatch.$className.$propertyName for at passe til en given klasse (f.eks typeMismatch.Book.author)
+typeMismatch.java.net.URL=Feltet {0} skal være en valid URL
+typeMismatch.java.net.URI=Feltet {0} skal være en valid URI
+typeMismatch.java.util.Date=Feltet {0} skal være en valid Dato
+typeMismatch.java.lang.Double=Feltet {0} skal være et valid tal
+typeMismatch.java.lang.Integer=Feltet {0} skal være et valid tal
+typeMismatch.java.lang.Long=Feltet {0} skal være et valid tal
+typeMismatch.java.lang.Short=Feltet {0} skal være et valid tal
+typeMismatch.java.math.BigDecimal=Feltet {0} skal være et valid tal
+typeMismatch.java.math.BigInteger=Feltet {0} skal være et valid tal
+
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_de.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_de.properties
new file mode 100644
index 0000000..173d489
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_de.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] entspricht nicht dem vorgegebenen Muster [{3}]
+default.invalid.url.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige URL
+default.invalid.creditCard.message=Das Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige Kreditkartennummer
+default.invalid.email.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gültige E-Mail Adresse
+default.invalid.range.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht im Wertebereich von [{3}] bis [{4}]
+default.invalid.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht im Wertebereich von [{3}] bis [{4}]
+default.invalid.max.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist größer als der Höchstwert von [{3}]
+default.invalid.min.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist kleiner als der Mindestwert von [{3}]
+default.invalid.max.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] übersteigt den Höchstwert von [{3}]
+default.invalid.min.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] unterschreitet den Mindestwert von [{3}]
+default.invalid.validator.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist ungültig
+default.not.inlist.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht in der Liste [{3}] enthalten.
+default.blank.message=Die Eigenschaft [{0}] des Typs [{1}] darf nicht leer sein
+default.not.equal.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] darf nicht gleich [{3}] sein
+default.null.message=Die Eigenschaft [{0}] des Typs [{1}] darf nicht null sein
+default.not.unique.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] darf nur einmal vorkommen
+
+default.paginate.prev=Vorherige
+default.paginate.next=Nächste
+default.boolean.true=Wahr
+default.boolean.false=Falsch
+default.date.format=dd.MM.yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} wurde angelegt
+default.updated.message={0} {1} wurde geändert
+default.deleted.message={0} {1} wurde gelöscht
+default.not.deleted.message={0} {1} konnte nicht gelöscht werden
+default.not.found.message={0} mit der id {1} wurde nicht gefunden
+default.optimistic.locking.failure=Ein anderer Benutzer hat das {0} Object geändert während Sie es bearbeitet haben
+
+default.home.label=Home
+default.list.label={0} Liste
+default.add.label={0} hinzufügen
+default.new.label={0} anlegen
+default.create.label={0} anlegen
+default.show.label={0} anzeigen
+default.edit.label={0} bearbeiten
+
+default.button.create.label=Anlegen
+default.button.edit.label=Bearbeiten
+default.button.update.label=Aktualisieren
+default.button.delete.label=Löschen
+default.button.delete.confirm.message=Sind Sie sicher?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Die Eigenschaft {0} muss eine gültige URL sein
+typeMismatch.java.net.URI=Die Eigenschaft {0} muss eine gültige URI sein
+typeMismatch.java.util.Date=Die Eigenschaft {0} muss ein gültiges Datum sein
+typeMismatch.java.lang.Double=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.lang.Integer=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.lang.Long=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.lang.Short=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.math.BigDecimal=Die Eigenschaft {0} muss eine gültige Zahl sein
+typeMismatch.java.math.BigInteger=Die Eigenschaft {0} muss eine gültige Zahl sein
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_es.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_es.properties
new file mode 100644
index 0000000..f0ede53
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_es.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no corresponde al patrón [{3}]
+default.invalid.url.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no es una URL válida
+default.invalid.creditCard.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no es un número de tarjeta de crédito válida
+default.invalid.email.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no es una dirección de correo electrónico válida
+default.invalid.range.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no entra en el rango válido de [{3}] a [{4}]
+default.invalid.size.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no entra en el tamaño válido de [{3}] a [{4}]
+default.invalid.max.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] excede el valor máximo [{3}]
+default.invalid.min.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] es menos que el valor mínimo [{3}]
+default.invalid.max.size.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] excede el tamaño máximo de [{3}]
+default.invalid.min.size.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] es menor que el tamaño mínimo de [{3}]
+default.invalid.validator.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no es válido
+default.not.inlist.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no esta contenido dentro de la lista [{3}]
+default.blank.message=La propiedad [{0}] de la clase [{1}] no puede ser vacía
+default.not.equal.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no puede igualar a [{3}]
+default.null.message=La propiedad [{0}] de la clase [{1}] no puede ser nulo
+default.not.unique.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] debe ser única
+
+default.paginate.prev=Anterior
+default.paginate.next=Siguiente
+default.boolean.true=Verdadero
+default.boolean.false=Falso
+default.date.format=yyyy-MM-dd HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} creado
+default.updated.message={0} {1} actualizado
+default.deleted.message={0} {1} eliminado
+default.not.deleted.message={0} {1} no puede eliminarse
+default.not.found.message=No se encuentra {0} con id {1}
+default.optimistic.locking.failure=Mientras usted editaba, otro usuario ha actualizado su {0}
+
+default.home.label=Principal
+default.list.label={0} Lista
+default.add.label=Agregar {0}
+default.new.label=Nuevo {0}
+default.create.label=Crear {0}
+default.show.label=Mostrar {0}
+default.edit.label=Editar {0}
+
+default.button.create.label=Crear
+default.button.edit.label=Editar
+default.button.update.label=Actualizar
+default.button.delete.label=Eliminar
+default.button.delete.confirm.message=¿Está usted seguro?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=La propiedad {0} debe ser una URL válida
+typeMismatch.java.net.URI=La propiedad {0} debe ser una URI válida
+typeMismatch.java.util.Date=La propiedad {0} debe ser una fecha válida
+typeMismatch.java.lang.Double=La propiedad {0} debe ser un número válido
+typeMismatch.java.lang.Integer=La propiedad {0} debe ser un número válido
+typeMismatch.java.lang.Long=La propiedad {0} debe ser un número válido
+typeMismatch.java.lang.Short=La propiedad {0} debe ser un número válido
+typeMismatch.java.math.BigDecimal=La propiedad {0} debe ser un número válido
+typeMismatch.java.math.BigInteger=La propiedad {0} debe ser un número válido
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_fr.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_fr.properties
new file mode 100644
index 0000000..5572164
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_fr.properties
@@ -0,0 +1,19 @@
+default.doesnt.match.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne correspond pas au pattern [{3}]
+default.invalid.url.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas une URL valide
+default.invalid.creditCard.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas un numéro de carte de crédit valide
+default.invalid.email.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas une adresse e-mail valide
+default.invalid.range.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas contenue dans l'intervalle [{3}] à [{4}]
+default.invalid.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas contenue dans l'intervalle [{3}] à [{4}]
+default.invalid.max.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est supérieure à la valeur maximum [{3}]
+default.invalid.min.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est inférieure à la valeur minimum [{3}]
+default.invalid.max.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est supérieure à la valeur maximum [{3}]
+default.invalid.min.size.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] est inférieure à la valeur minimum [{3}]
+default.invalid.validator.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas valide
+default.not.inlist.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne fait pas partie de la liste [{3}]
+default.blank.message=La propriété [{0}] de la classe [{1}] ne peut pas être vide
+default.not.equal.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] ne peut pas être égale à [{3}]
+default.null.message=La propriété [{0}] de la classe [{1}] ne peut pas être nulle
+default.not.unique.message=La propriété [{0}] de la classe [{1}] avec la valeur [{2}] doit être unique
+
+default.paginate.prev=Précédent
+default.paginate.next=Suivant
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_it.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_it.properties
new file mode 100644
index 0000000..a90f1c7
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_it.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non corrisponde al pattern [{3}]
+default.invalid.url.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un URL valido
+default.invalid.creditCard.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un numero di carta di credito valido
+default.invalid.email.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è un indirizzo email valido
+default.invalid.range.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non rientra nell'intervallo valido da [{3}] a [{4}]
+default.invalid.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non rientra nell'intervallo di dimensioni valide da [{3}] a [{4}]
+default.invalid.max.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è maggiore di [{3}]
+default.invalid.min.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è minore di [{3}]
+default.invalid.max.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è maggiore di [{3}]
+default.invalid.min.size.message=La proprietà [{0}] della classe [{1}] con valore [{2}] è minore di [{3}]
+default.invalid.validator.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è valida
+default.not.inlist.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non è contenuta nella lista [{3}]
+default.blank.message=La proprietà [{0}] della classe [{1}] non può essere vuota
+default.not.equal.message=La proprietà [{0}] della classe [{1}] con valore [{2}] non può essere uguale a [{3}]
+default.null.message=La proprietà [{0}] della classe [{1}] non può essere null
+default.not.unique.message=La proprietà [{0}] della classe [{1}] con valore [{2}] deve essere unica
+
+default.paginate.prev=Precedente
+default.paginate.next=Successivo
+default.boolean.true=Vero
+default.boolean.false=Falso
+default.date.format=dd/MM/yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} creato
+default.updated.message={0} {1} aggiornato
+default.deleted.message={0} {1} eliminato
+default.not.deleted.message={0} {1} non può essere eliminato
+default.not.found.message={0} non trovato con id {1}
+default.optimistic.locking.failure=Un altro utente ha aggiornato questo {0} mentre si era in modifica
+
+default.home.label=Home
+default.list.label={0} Elenco
+default.add.label=Aggiungi {0}
+default.new.label=Nuovo {0}
+default.create.label=Crea {0}
+default.show.label=Mostra {0}
+default.edit.label=Modifica {0}
+
+default.button.create.label=Crea
+default.button.edit.label=Modifica
+default.button.update.label=Aggiorna
+default.button.delete.label=Elimina
+default.button.delete.confirm.message=Si è sicuri?
+
+# Data binding errors. Usa "typeMismatch.$className.$propertyName per la personalizzazione (es typeMismatch.Book.author)
+typeMismatch.java.net.URL=La proprietà {0} deve essere un URL valido
+typeMismatch.java.net.URI=La proprietà {0} deve essere un URI valido
+typeMismatch.java.util.Date=La proprietà {0} deve essere una data valida
+typeMismatch.java.lang.Double=La proprietà {0} deve essere un numero valido
+typeMismatch.java.lang.Integer=La proprietà {0} deve essere un numero valido
+typeMismatch.java.lang.Long=La proprietà {0} deve essere un numero valido
+typeMismatch.java.lang.Short=La proprietà {0} deve essere un numero valido
+typeMismatch.java.math.BigDecimal=La proprietà {0} deve essere un numero valido
+typeMismatch.java.math.BigInteger=La proprietà {0} deve essere un numero valido
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_ja.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_ja.properties
new file mode 100644
index 0000000..f716d75
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_ja.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]パターンと一致していません。
+default.invalid.url.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なURLではありません。
+default.invalid.creditCard.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なクレジットカード番号ではありません。
+default.invalid.email.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、有効なメールアドレスではありません。
+default.invalid.range.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]から[{4}]範囲内を指定してください。
+default.invalid.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]から[{4}]以内を指定してください。
+default.invalid.max.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最大値[{3}]より大きいです。
+default.invalid.min.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最小値[{3}]より小さいです。
+default.invalid.max.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最大値[{3}]より大きいです。
+default.invalid.min.size.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、最小値[{3}]より小さいです。
+default.invalid.validator.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、カスタムバリデーションを通過できません。
+default.not.inlist.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]リスト内に存在しません。
+default.blank.message=[{1}]クラスのプロパティ[{0}]の空白は許可されません。
+default.not.equal.message=クラス[{1}]プロパティ[{0}]の値[{2}]は、[{3}]と同等ではありません。
+default.null.message=[{1}]クラスのプロパティ[{0}]にnullは許可されません。
+default.not.unique.message=クラス[{1}]プロパティ[{0}]の値[{2}]は既に使用されています。
+
+default.paginate.prev=戻る
+default.paginate.next=次へ
+default.boolean.true=はい
+default.boolean.false=いいえ
+default.date.format=yyyy/MM/dd HH:mm:ss z
+default.number.format=0
+
+default.created.message={0}(id:{1})を作成しました。
+default.updated.message={0}(id:{1})を更新しました。
+default.deleted.message={0}(id:{1})を削除しました。
+default.not.deleted.message={0}(id:{1})は削除できませんでした。
+default.not.found.message={0}(id:{1})は見つかりませんでした。
+default.optimistic.locking.failure=この{0}は編集中に他のユーザによって先に更新されています。
+
+default.home.label=ホーム
+default.list.label={0}リスト
+default.add.label={0}を追加
+default.new.label={0}を新規作成
+default.create.label={0}を作成
+default.show.label={0}詳細
+default.edit.label={0}を編集
+
+default.button.create.label=作成
+default.button.edit.label=編集
+default.button.update.label=更新
+default.button.delete.label=削除
+default.button.delete.confirm.message=本当に削除してよろしいですか?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL={0}は有効なURLでなければなりません。
+typeMismatch.java.net.URI={0}は有効なURIでなければなりません。
+typeMismatch.java.util.Date={0}は有効な日付でなければなりません。
+typeMismatch.java.lang.Double={0}は有効な数値でなければなりません。
+typeMismatch.java.lang.Integer={0}は有効な数値でなければなりません。
+typeMismatch.java.lang.Long={0}は有効な数値でなければなりません。
+typeMismatch.java.lang.Short={0}は有効な数値でなければなりません。
+typeMismatch.java.math.BigDecimal={0}は有効な数値でなければなりません。
+typeMismatch.java.math.BigInteger={0}は有効な数値でなければなりません。
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_nl.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_nl.properties
new file mode 100644
index 0000000..cd5cc94
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_nl.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] komt niet overeen met het vereiste patroon [{3}]
+default.invalid.url.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is geen geldige URL
+default.invalid.creditCard.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is geen geldig credit card nummer
+default.invalid.email.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is geen geldig e-mailadres
+default.invalid.range.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] valt niet in de geldige waardenreeks van [{3}] tot [{4}]
+default.invalid.size.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] valt niet in de geldige grootte van [{3}] tot [{4}]
+default.invalid.max.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] overschrijdt de maximumwaarde [{3}]
+default.invalid.min.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is minder dan de minimumwaarde [{3}]
+default.invalid.max.size.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] overschrijdt de maximumgrootte van [{3}]
+default.invalid.min.size.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is minder dan minimumgrootte van [{3}]
+default.invalid.validator.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is niet geldig
+default.not.inlist.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] komt niet voor in de lijst [{3}]
+default.blank.message=Attribuut [{0}] van entiteit [{1}] mag niet leeg zijn
+default.not.equal.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] mag niet gelijk zijn aan [{3}]
+default.null.message=Attribuut [{0}] van entiteit [{1}] mag niet leeg zijn
+default.not.unique.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] moet uniek zijn
+
+default.paginate.prev=Vorige
+default.paginate.next=Volgende
+default.boolean.true=Ja
+default.boolean.false=Nee
+default.date.format=dd-MM-yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} ingevoerd
+default.updated.message={0} {1} gewijzigd
+default.deleted.message={0} {1} verwijderd
+default.not.deleted.message={0} {1} kon niet worden verwijderd
+default.not.found.message={0} met id {1} kon niet worden gevonden
+default.optimistic.locking.failure=Een andere gebruiker heeft deze {0} al gewijzigd
+
+default.home.label=Home
+default.list.label={0} Overzicht
+default.add.label=Toevoegen {0}
+default.new.label=Invoeren {0}
+default.create.label=Invoeren {0}
+default.show.label=Details {0}
+default.edit.label=Wijzigen {0}
+
+default.button.create.label=Invoeren
+default.button.edit.label=Wijzigen
+default.button.update.label=Opslaan
+default.button.delete.label=Verwijderen
+default.button.delete.confirm.message=Weet je het zeker?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Attribuut {0} is geen geldige URL
+typeMismatch.java.net.URI=Attribuut {0} is geen geldige URI
+typeMismatch.java.util.Date=Attribuut {0} is geen geldige datum
+typeMismatch.java.lang.Double=Attribuut {0} is geen geldig nummer
+typeMismatch.java.lang.Integer=Attribuut {0} is geen geldig nummer
+typeMismatch.java.lang.Long=Attribuut {0} is geen geldig nummer
+typeMismatch.java.lang.Short=Attribuut {0} is geen geldig nummer
+typeMismatch.java.math.BigDecimal=Attribuut {0} is geen geldig nummer
+typeMismatch.java.math.BigInteger=Attribuut {0} is geen geldig nummer
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_pl.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_pl.properties
new file mode 100644
index 0000000..959296c
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_pl.properties
@@ -0,0 +1,59 @@
+#
+# Translated by Matthias Hryniszak - padcom@gmail.com
+#
+
+default.doesnt.match.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] nie pasuje do wymaganego wzorca [{3}]
+default.invalid.url.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] jest niepoprawnym adresem URL
+default.invalid.creditCard.message=Właściwość [{0}] klasy [{1}] with value [{2}] nie jest poprawnym numerem karty kredytowej
+default.invalid.email.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] nie jest poprawnym adresem e-mail
+default.invalid.range.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] nie zawiera się zakładanym zakresie od [{3}] do [{4}]
+default.invalid.size.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] nie zawiera się w zakładanym zakresie rozmiarów od [{3}] do [{4}]
+default.invalid.max.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] przekracza maksymalną wartość [{3}]
+default.invalid.min.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] jest mniejsza niż minimalna wartość [{3}]
+default.invalid.max.size.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] przekracza maksymalny rozmiar [{3}]
+default.invalid.min.size.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] jest mniejsza niż minimalny rozmiar [{3}]
+default.invalid.validator.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] nie spełnia założonych niestandardowych warunków
+default.not.inlist.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] nie zawiera się w liście [{3}]
+default.blank.message=Właściwość [{0}] klasy [{1}] nie może być pusta
+default.not.equal.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] nie może równać się [{3}]
+default.null.message=Właściwość [{0}] klasy [{1}] nie może być null
+default.not.unique.message=Właściwość [{0}] klasy [{1}] o wartości [{2}] musi być unikalna
+
+default.paginate.prev=Poprzedni
+default.paginate.next=Następny
+default.boolean.true=Prawda
+default.boolean.false=Fałsz
+default.date.format=yyyy-MM-dd HH:mm:ss z
+default.number.format=0
+
+default.created.message=Utworzono {0} {1}
+default.updated.message=Zaktualizowano {0} {1}
+default.deleted.message=Usunięto {0} {1}
+default.not.deleted.message={0} {1} nie mógł zostać usunięty
+default.not.found.message=Nie znaleziono {0} o id {1}
+default.optimistic.locking.failure=Inny użytkownik zaktualizował ten obiekt {0} w trakcie twoich zmian
+
+default.home.label=Strona domowa
+default.list.label=Lista {0}
+default.add.label=Dodaj {0}
+default.new.label=Utwórz {0}
+default.create.label=Utwórz {0}
+default.show.label=Pokaż {0}
+default.edit.label=Edytuj {0}
+
+default.button.create.label=Utwórz
+default.button.edit.label=Edytuj
+default.button.update.label=Zaktualizuj
+default.button.delete.label=Usuń
+default.button.delete.confirm.message=Czy jesteś pewien?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Właściwość {0} musi być poprawnym adresem URL
+typeMismatch.java.net.URI=Właściwość {0} musi być poprawnym adresem URI
+typeMismatch.java.util.Date=Właściwość {0} musi być poprawną datą
+typeMismatch.java.lang.Double=Właściwość {0} musi być poprawnyą liczbą
+typeMismatch.java.lang.Integer=Właściwość {0} musi być poprawnyą liczbą
+typeMismatch.java.lang.Long=Właściwość {0} musi być poprawnyą liczbą
+typeMismatch.java.lang.Short=Właściwość {0} musi być poprawnyą liczbą
+typeMismatch.java.math.BigDecimal=Właściwość {0} musi być poprawnyą liczbą
+typeMismatch.java.math.BigInteger=Właściwość {0} musi być poprawnyą liczbą
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_pt_BR.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_pt_BR.properties
new file mode 100644
index 0000000..0c368f2
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_pt_BR.properties
@@ -0,0 +1,59 @@
+#
+# Translated by Lucas Teixeira - lucastex@gmail.com
+#
+
+default.doesnt.match.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atende ao padrão definido [{3}]
+default.invalid.url.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é uma URL válida
+default.invalid.creditCard.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um número válido de cartão de crédito
+default.invalid.email.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um endereço de email válido.
+default.invalid.range.message=O campo [{0}] da classe [{1}] com o valor [{2}] não está entre a faixa de valores válida de [{3}] até [{4}]
+default.invalid.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] não está na faixa de tamanho válida de [{3}] até [{4}]
+default.invalid.max.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapass o valor máximo [{3}]
+default.invalid.min.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o valor mínimo [{3}]
+default.invalid.max.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o tamanho máximo de [{3}]
+default.invalid.min.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o tamanho mínimo de [{3}]
+default.invalid.validator.message=O campo [{0}] da classe [{1}] com o valor [{2}] não passou na validação
+default.not.inlist.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um valor dentre os permitidos na lista [{3}]
+default.blank.message=O campo [{0}] da classe [{1}] não pode ficar em branco
+default.not.equal.message=O campo [{0}] da classe [{1}] com o valor [{2}] não pode ser igual a [{3}]
+default.null.message=O campo [{0}] da classe [{1}] não pode ser vazia
+default.not.unique.message=O campo [{0}] da classe [{1}] com o valor [{2}] deve ser único
+
+default.paginate.prev=Anterior
+default.paginate.next=Próximo
+default.boolean.true=Sim
+default.boolean.false=Não
+default.date.format=dd/MM/yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} criado
+default.updated.message={0} {1} atualizado
+default.deleted.message={0} {1} removido
+default.not.deleted.message={0} {1} não pode ser removido
+default.not.found.message={0} não foi encontrado com id {1}
+default.optimistic.locking.failure=Outro usuário atualizou este [{0}] enquanto você tentou salvá-lo
+
+default.home.label=Principal
+default.list.label={0} Listagem
+default.add.label=Adicionar {0}
+default.new.label=Novo {0}
+default.create.label=Criar {0}
+default.show.label=Ver {0}
+default.edit.label=Editar {0}
+
+default.button.create.label=Criar
+default.button.edit.label=Editar
+default.button.update.label=Alterar
+default.button.delete.label=Remover
+default.button.delete.confirm.message=Tem certeza?
+
+# Mensagens de erro em atribuição de valores. Use "typeMismatch.$className.$propertyName" para customizar (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=O campo {0} deve ser uma URL válida.
+typeMismatch.java.net.URI=O campo {0} deve ser uma URI válida.
+typeMismatch.java.util.Date=O campo {0} deve ser uma data válida
+typeMismatch.java.lang.Double=O campo {0} deve ser um número válido.
+typeMismatch.java.lang.Integer=O campo {0} deve ser um número válido.
+typeMismatch.java.lang.Long=O campo {0} deve ser um número válido.
+typeMismatch.java.lang.Short=O campo {0} deve ser um número válido.
+typeMismatch.java.math.BigDecimal=O campo {0} deve ser um número válido.
+typeMismatch.java.math.BigInteger=O campo {0} deve ser um número válido.
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_pt_PT.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_pt_PT.properties
new file mode 100644
index 0000000..a386070
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_pt_PT.properties
@@ -0,0 +1,34 @@
+#
+# translation by miguel.ping@gmail.com, based on pt_BR translation by Lucas Teixeira - lucastex@gmail.com
+#
+
+default.doesnt.match.message=O campo [{0}] da classe [{1}] com o valor [{2}] não corresponde ao padrão definido [{3}]
+default.invalid.url.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um URL válido
+default.invalid.creditCard.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um número válido de cartão de crédito
+default.invalid.email.message=O campo [{0}] da classe [{1}] com o valor [{2}] não é um endereço de email válido.
+default.invalid.range.message=O campo [{0}] da classe [{1}] com o valor [{2}] não está dentro dos limites de valores válidos de [{3}] a [{4}]
+default.invalid.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] está fora dos limites de tamanho válido de [{3}] a [{4}]
+default.invalid.max.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o valor máximo [{3}]
+default.invalid.min.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o valor mínimo [{3}]
+default.invalid.max.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o tamanho máximo de [{3}]
+default.invalid.min.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] não atinge o tamanho mínimo de [{3}]
+default.invalid.validator.message=O campo [{0}] da classe [{1}] com o valor [{2}] não passou na validação
+default.not.inlist.message=O campo [{0}] da classe [{1}] com o valor [{2}] não se encontra nos valores permitidos da lista [{3}]
+default.blank.message=O campo [{0}] da classe [{1}] não pode ser vazio
+default.not.equal.message=O campo [{0}] da classe [{1}] com o valor [{2}] não pode ser igual a [{3}]
+default.null.message=O campo [{0}] da classe [{1}] não pode ser vazio
+default.not.unique.message=O campo [{0}] da classe [{1}] com o valor [{2}] deve ser único
+
+default.paginate.prev=Anterior
+default.paginate.next=Próximo
+
+# Mensagens de erro em atribuição de valores. Use "typeMismatch.$className.$propertyName" para personalizar(eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=O campo {0} deve ser um URL válido.
+typeMismatch.java.net.URI=O campo {0} deve ser um URI válido.
+typeMismatch.java.util.Date=O campo {0} deve ser uma data válida
+typeMismatch.java.lang.Double=O campo {0} deve ser um número válido.
+typeMismatch.java.lang.Integer=O campo {0} deve ser um número válido.
+typeMismatch.java.lang.Long=O campo {0} deve ser um número valido.
+typeMismatch.java.lang.Short=O campo {0} deve ser um número válido.
+typeMismatch.java.math.BigDecimal=O campo {0} deve ser um número válido.
+typeMismatch.java.math.BigInteger=O campo {0} deve ser um número válido.
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_ru.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_ru.properties
new file mode 100644
index 0000000..53a4bdc
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_ru.properties
@@ -0,0 +1,31 @@
+default.doesnt.match.message=Значение [{2}] поля [{0}] класса [{1}] не соответствует образцу [{3}]
+default.invalid.url.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым URL-адресом
+default.invalid.creditCard.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым номером кредитной карты
+default.invalid.email.message=Значение [{2}] поля [{0}] класса [{1}] не является допустимым e-mail адресом
+default.invalid.range.message=Значение [{2}] поля [{0}] класса [{1}] не попадает в допустимый интервал от [{3}] до [{4}]
+default.invalid.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) не попадает в допустимый интервал от [{3}] до [{4}]
+default.invalid.max.message=Значение [{2}] поля [{0}] класса [{1}] больше чем максимально допустимое значение [{3}]
+default.invalid.min.message=Значение [{2}] поля [{0}] класса [{1}] меньше чем минимально допустимое значение [{3}]
+default.invalid.max.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) больше чем максимально допустимый размер [{3}]
+default.invalid.min.size.message=Размер поля [{0}] класса [{1}] (значение: [{2}]) меньше чем минимально допустимый размер [{3}]
+default.invalid.validator.message=Значение [{2}] поля [{0}] класса [{1}] не допустимо
+default.not.inlist.message=Значение [{2}] поля [{0}] класса [{1}] не попадает в список допустимых значений [{3}]
+default.blank.message=Поле [{0}] класса [{1}] не может быть пустым
+default.not.equal.message=Значение [{2}] поля [{0}] класса [{1}] не может быть равно [{3}]
+default.null.message=Поле [{0}] класса [{1}] не может иметь значение null
+default.not.unique.message=Значение [{2}] поля [{0}] класса [{1}] должно быть уникальным
+
+default.paginate.prev=Предыдушая страница
+default.paginate.next=Следующая страница
+
+# Ошибки при присвоении данных. Для точной настройки для полей классов используйте
+# формат "typeMismatch.$className.$propertyName" (например, typeMismatch.Book.author)
+typeMismatch.java.net.URL=Значение поля {0} не является допустимым URL
+typeMismatch.java.net.URI=Значение поля {0} не является допустимым URI
+typeMismatch.java.util.Date=Значение поля {0} не является допустимой датой
+typeMismatch.java.lang.Double=Значение поля {0} не является допустимым числом
+typeMismatch.java.lang.Integer=Значение поля {0} не является допустимым числом
+typeMismatch.java.lang.Long=Значение поля {0} не является допустимым числом
+typeMismatch.java.lang.Short=Значение поля {0} не является допустимым числом
+typeMismatch.java.math.BigDecimal=Значение поля {0} не является допустимым числом
+typeMismatch.java.math.BigInteger=Значение поля {0} не является допустимым числом
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_sv.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_sv.properties
new file mode 100644
index 0000000..61899d7
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_sv.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=Attributet [{0}] för klassen [{1}] med värde [{2}] matchar inte mot uttrycket [{3}]
+default.invalid.url.message=Attributet [{0}] för klassen [{1}] med värde [{2}] är inte en giltig URL
+default.invalid.creditCard.message=Attributet [{0}] för klassen [{1}] med värde [{2}] är inte ett giltigt kreditkortsnummer
+default.invalid.email.message=Attributet [{0}] för klassen [{1}] med värde [{2}] är inte en giltig e-postadress
+default.invalid.range.message=Attributet [{0}] för klassen [{1}] med värde [{2}] är inte inom intervallet [{3}] till [{4}]
+default.invalid.size.message=Attributet [{0}] för klassen [{1}] med värde [{2}] har en storlek som inte är inom [{3}] till [{4}]
+default.invalid.max.message=Attributet [{0}] för klassen [{1}] med värde [{2}] överskrider maxvärdet [{3}]
+default.invalid.min.message=Attributet [{0}] för klassen [{1}] med värde [{2}] är mindre än minimivärdet [{3}]
+default.invalid.max.size.message=Attributet [{0}] för klassen [{1}] med värde [{2}] överskrider maxstorleken [{3}]
+default.invalid.min.size.message=Attributet [{0}] för klassen [{1}] med värde [{2}] är mindre än minimistorleken [{3}]
+default.invalid.validator.message=Attributet [{0}] för klassen [{1}] med värde [{2}] är inte giltigt enligt anpassad regel
+default.not.inlist.message=Attributet [{0}] för klassen [{1}] med värde [{2}] är inte giltigt, måste vara ett av [{3}]
+default.blank.message=Attributet [{0}] för klassen [{1}] får inte vara tomt
+default.not.equal.message=Attributet [{0}] för klassen [{1}] med värde [{2}] får inte vara lika med [{3}]
+default.null.message=Attributet [{0}] för klassen [{1}] får inte vara tomt
+default.not.unique.message=Attributet [{0}] för klassen [{1}] med värde [{2}] måste vara unikt
+
+default.paginate.prev=Föregående
+default.paginate.next=Nästa
+default.boolean.true=Sant
+default.boolean.false=Falskt
+default.date.format=yyyy-MM-dd HH:mm:ss z
+default.number.format=0
+
+default.created.message={0} {1} skapades
+default.updated.message={0} {1} uppdaterades
+default.deleted.message={0} {1} borttagen
+default.not.deleted.message={0} {1} kunde inte tas bort
+default.not.found.message={0} med id {1} kunde inte hittas
+default.optimistic.locking.failure=En annan användare har uppdaterat det här {0} objektet medan du redigerade det
+
+default.home.label=Hem
+default.list.label= {0} - Lista
+default.add.label=Lägg till {0}
+default.new.label=Skapa {0}
+default.create.label=Skapa {0}
+default.show.label=Visa {0}
+default.edit.label=Ändra {0}
+
+default.button.create.label=Skapa
+default.button.edit.label=Ändra
+default.button.update.label=Uppdatera
+default.button.delete.label=Ta bort
+default.button.delete.confirm.message=Är du säker?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Värdet för {0} måste vara en giltig URL
+typeMismatch.java.net.URI=Värdet för {0} måste vara en giltig URI
+typeMismatch.java.util.Date=Värdet {0} måste vara ett giltigt datum
+typeMismatch.java.lang.Double=Värdet {0} måste vara ett giltigt nummer
+typeMismatch.java.lang.Integer=Värdet {0} måste vara ett giltigt heltal
+typeMismatch.java.lang.Long=Värdet {0} måste vara ett giltigt heltal
+typeMismatch.java.lang.Short=Värdet {0} måste vara ett giltigt heltal
+typeMismatch.java.math.BigDecimal=Värdet {0} måste vara ett giltigt nummer
+typeMismatch.java.math.BigInteger=Värdet {0} måste vara ett giltigt heltal
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_th.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_th.properties
new file mode 100644
index 0000000..31c8668
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_th.properties
@@ -0,0 +1,55 @@
+default.doesnt.match.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบที่กำหนดไว้ใน [{3}]
+default.invalid.url.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบ URL
+default.invalid.creditCard.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบหมายเลขบัตรเครดิต
+default.invalid.email.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ถูกต้องตามรูปแบบอีเมล์
+default.invalid.range.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้มีค่าที่ถูกต้องในช่วงจาก [{3}] ถึง [{4}]
+default.invalid.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้มีขนาดที่ถูกต้องในช่วงจาก [{3}] ถึง [{4}]
+default.invalid.max.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีค่าเกิดกว่าค่ามากสุด [{3}]
+default.invalid.min.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีค่าน้อยกว่าค่าต่ำสุด [{3}]
+default.invalid.max.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีขนาดเกินกว่าขนาดมากสุดของ [{3}]
+default.invalid.min.size.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] มีขนาดต่ำกว่าขนาดต่ำสุดของ [{3}]
+default.invalid.validator.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ผ่านการทวนสอบค่าที่ตั้งขึ้น
+default.not.inlist.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่ได้อยู่ในรายการต่อไปนี้ [{3}]
+default.blank.message=คุณสมบัติ [{0}] ของคลาส [{1}] ไม่สามารถเป็นค่าว่างได้
+default.not.equal.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] ไม่สามารถเท่ากับ [{3}] ได้
+default.null.message=คุณสมบัติ [{0}] ของคลาส [{1}] ไม่สามารถเป็น null ได้
+default.not.unique.message=คุณสมบัติ [{0}] ของคลาส [{1}] ซึ่งมีค่าเป็น [{2}] จะต้องไม่ซ้ำ (unique)
+
+default.paginate.prev=ก่อนหน้า
+default.paginate.next=ถัดไป
+default.boolean.true=จริง
+default.boolean.false=เท็จ
+default.date.format=dd-MM-yyyy HH:mm:ss z
+default.number.format=0
+
+default.created.message=สร้าง {0} {1} เรียบร้อยแล้ว
+default.updated.message=ปรับปรุง {0} {1} เรียบร้อยแล้ว
+default.deleted.message=ลบ {0} {1} เรียบร้อยแล้ว
+default.not.deleted.message=ไม่สามารถลบ {0} {1}
+default.not.found.message=ไม่พบ {0} ด้วย id {1} นี้
+default.optimistic.locking.failure=มีผู้ใช้ท่านอื่นปรับปรุง {0} ขณะที่คุณกำลังแก้ไขข้อมูลอยู่
+
+default.home.label=หน้าแรก
+default.list.label=รายการ {0}
+default.add.label=เพิ่ม {0}
+default.new.label=สร้าง {0} ใหม่
+default.create.label=สร้าง {0}
+default.show.label=แสดง {0}
+default.edit.label=แก้ไข {0}
+
+default.button.create.label=สร้าง
+default.button.edit.label=แก้ไข
+default.button.update.label=ปรับปรุง
+default.button.delete.label=ลบ
+default.button.delete.confirm.message=คุณแน่ใจหรือไม่ ?
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=คุณสมบัติ '{0}' จะต้องเป็นค่า URL ที่ถูกต้อง
+typeMismatch.java.net.URI=คุณสมบัติ '{0}' จะต้องเป็นค่า URI ที่ถูกต้อง
+typeMismatch.java.util.Date=คุณสมบัติ '{0}' จะต้องมีค่าเป็นวันที่
+typeMismatch.java.lang.Double=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Double
+typeMismatch.java.lang.Integer=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Integer
+typeMismatch.java.lang.Long=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Long
+typeMismatch.java.lang.Short=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท Short
+typeMismatch.java.math.BigDecimal=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท BigDecimal
+typeMismatch.java.math.BigInteger=คุณสมบัติ '{0}' จะต้องมีค่าเป็นจำนวนประเภท BigInteger
diff --git a/ch09/ch10/demo-grails/grails-app/i18n/messages_zh_CN.properties b/ch09/ch10/demo-grails/grails-app/i18n/messages_zh_CN.properties
new file mode 100644
index 0000000..b89bc93
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/i18n/messages_zh_CN.properties
@@ -0,0 +1,18 @@
+default.blank.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u4E0D\u80FD\u4E3A\u7A7A
+default.doesnt.match.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0E\u5B9A\u4E49\u7684\u6A21\u5F0F [{3}]\u4E0D\u5339\u914D
+default.invalid.creditCard.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u4FE1\u7528\u5361\u53F7
+default.invalid.email.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u5408\u6CD5\u7684\u7535\u5B50\u90AE\u4EF6\u5730\u5740
+default.invalid.max.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u6BD4\u6700\u5927\u503C [{3}]\u8FD8\u5927
+default.invalid.max.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u6BD4\u6700\u5927\u503C [{3}]\u8FD8\u5927
+default.invalid.min.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u6BD4\u6700\u5C0F\u503C [{3}]\u8FD8\u5C0F
+default.invalid.min.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u6BD4\u6700\u5C0F\u503C [{3}]\u8FD8\u5C0F
+default.invalid.range.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u5728\u5408\u6CD5\u7684\u8303\u56F4\u5185( [{3}] \uFF5E [{4}] )
+default.invalid.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u4E0D\u5728\u5408\u6CD5\u7684\u8303\u56F4\u5185( [{3}] \uFF5E [{4}] )
+default.invalid.url.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u5408\u6CD5\u7684URL
+default.invalid.validator.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u672A\u80FD\u901A\u8FC7\u81EA\u5B9A\u4E49\u7684\u9A8C\u8BC1
+default.not.equal.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0E[{3}]\u4E0D\u76F8\u7B49
+default.not.inlist.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u5728\u5217\u8868\u7684\u53D6\u503C\u8303\u56F4\u5185
+default.not.unique.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u5FC5\u987B\u662F\u552F\u4E00\u7684
+default.null.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u4E0D\u80FD\u4E3Anull
+default.paginate.next=\u4E0B\u9875
+default.paginate.prev=\u4E0A\u9875
diff --git a/ch09/ch10/demo-grails/grails-app/views/error.gsp b/ch09/ch10/demo-grails/grails-app/views/error.gsp
new file mode 100644
index 0000000..3dcbdd1
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/views/error.gsp
@@ -0,0 +1,11 @@
+
+
+
+ Grails Runtime Exception
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo-grails/grails-app/views/index.gsp b/ch09/ch10/demo-grails/grails-app/views/index.gsp
new file mode 100644
index 0000000..86df4da
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/views/index.gsp
@@ -0,0 +1,122 @@
+
+
+
+
+ Welcome to Grails
+
+
+
+
+
+
Application Status
+
+ App version:
+ Grails version:
+ Groovy version: ${org.codehaus.groovy.runtime.InvokerHelper.getVersion()}
+ JVM version: ${System.getProperty('java.version')}
+ Reloading active: ${grails.util.Environment.reloadingAgentEnabled}
+ Controllers: ${grailsApplication.controllerClasses.size()}
+ Domains: ${grailsApplication.domainClasses.size()}
+ Services: ${grailsApplication.serviceClasses.size()}
+ Tag Libraries: ${grailsApplication.tagLibClasses.size()}
+
+
Installed Plugins
+
+
+ ${plugin.name} - ${plugin.version}
+
+
+
+
+
Welcome to Grails
+
Congratulations, you have successfully started your first Grails application! At the moment
+ this is the default page, feel free to modify it to either redirect to a controller or display whatever
+ content you may choose. Below is a list of controllers that are currently deployed in this application,
+ click on each to execute its default action:
+
+
+
Available Controllers:
+
+
+
+
+
diff --git a/ch09/ch10/demo-grails/grails-app/views/layouts/main.gsp b/ch09/ch10/demo-grails/grails-app/views/layouts/main.gsp
new file mode 100644
index 0000000..c69c988
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/views/layouts/main.gsp
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo-grails/grails-app/views/login/auth.gsp b/ch09/ch10/demo-grails/grails-app/views/login/auth.gsp
new file mode 100644
index 0000000..2bba9f9
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/views/login/auth.gsp
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${flash.message}
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo-grails/grails-app/views/login/denied.gsp b/ch09/ch10/demo-grails/grails-app/views/login/denied.gsp
new file mode 100644
index 0000000..833a158
--- /dev/null
+++ b/ch09/ch10/demo-grails/grails-app/views/login/denied.gsp
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources$_run_closure1.class
new file mode 100644
index 0000000..bbb497f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources$_run_closure1_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources$_run_closure1_closure2.class
new file mode 100644
index 0000000..caba913
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources$_run_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources.class b/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources.class
new file mode 100644
index 0000000..24c6376
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/ApplicationResources.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap$_closure1.class
new file mode 100644
index 0000000..13c8ce9
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap$_closure2.class
new file mode 100644
index 0000000..040e67b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap.class b/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap.class
new file mode 100644
index 0000000..ca41a4f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BootStrap.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1.class
new file mode 100644
index 0000000..8af4045
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure2.class
new file mode 100644
index 0000000..7d3f214
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure3.class
new file mode 100644
index 0000000..fa2828f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure4.class
new file mode 100644
index 0000000..8c71734
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure5.class
new file mode 100644
index 0000000..88c1006
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig$_run_closure1_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig.class b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig.class
new file mode 100644
index 0000000..b6d906d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/BuildConfig.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1.class
new file mode 100644
index 0000000..37f8391
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1_closure3.class
new file mode 100644
index 0000000..918be82
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1_closure4.class
new file mode 100644
index 0000000..8b41ccf
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure1_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure2.class
new file mode 100644
index 0000000..0f81823
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/Config$_run_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/Config.class b/ch09/ch10/demo-grails/target-eclipse/classes/Config.class
new file mode 100644
index 0000000..8d6a0a5
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/Config.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure1.class
new file mode 100644
index 0000000..178ae82
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure2.class
new file mode 100644
index 0000000..c13610b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3.class
new file mode 100644
index 0000000..f9bfa63
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure4.class
new file mode 100644
index 0000000..c4a26f6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure4_closure7.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure4_closure7.class
new file mode 100644
index 0000000..cdf042e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure4_closure7.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure5.class
new file mode 100644
index 0000000..0cac5e7
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure5_closure8.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure5_closure8.class
new file mode 100644
index 0000000..7d63db4
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure5_closure8.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6.class
new file mode 100644
index 0000000..1175bf4
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6_closure9.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6_closure9.class
new file mode 100644
index 0000000..373c8c3
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6_closure9.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6_closure9_closure10.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6_closure9_closure10.class
new file mode 100644
index 0000000..15cec06
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource$_run_closure3_closure6_closure9_closure10.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DataSource.class b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource.class
new file mode 100644
index 0000000..19ceadd
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DataSource.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DbdocUrlMappings$__clinit__closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/DbdocUrlMappings$__clinit__closure1.class
new file mode 100644
index 0000000..c71b228
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DbdocUrlMappings$__clinit__closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DbdocUrlMappings.class b/ch09/ch10/demo-grails/target-eclipse/classes/DbdocUrlMappings.class
new file mode 100644
index 0000000..7a5098b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DbdocUrlMappings.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1.class
new file mode 100644
index 0000000..ce4daeb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1_closure2.class
new file mode 100644
index 0000000..e13b716
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1_closure3.class
new file mode 100644
index 0000000..1cbce9f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig$_run_closure1_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig.class b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig.class
new file mode 100644
index 0000000..8f3b806
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultCacheConfig.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DefaultSecurityConfig$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultSecurityConfig$_run_closure1.class
new file mode 100644
index 0000000..5b6183b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultSecurityConfig$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/DefaultSecurityConfig.class b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultSecurityConfig.class
new file mode 100644
index 0000000..28e13ef
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/DefaultSecurityConfig.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryConfig$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryConfig$_run_closure1.class
new file mode 100644
index 0000000..934db4a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryConfig$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryConfig.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryConfig.class
new file mode 100644
index 0000000..aaa3e3e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryConfig.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1.class
new file mode 100644
index 0000000..bf41bbb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1_closure2.class
new file mode 100644
index 0000000..ee00dda
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1_closure3.class
new file mode 100644
index 0000000..ef08c2d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources$_run_closure1_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources.class
new file mode 100644
index 0000000..981ecd8
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryPluginResources.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure1.class
new file mode 100644
index 0000000..67bf00d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2.class
new file mode 100644
index 0000000..556a82d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure4.class
new file mode 100644
index 0000000..6fa5ad2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure5.class
new file mode 100644
index 0000000..6f0dd29
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure6.class
new file mode 100644
index 0000000..e111b46
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure7.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure7.class
new file mode 100644
index 0000000..96583cc
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure2_closure7.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure3.class
new file mode 100644
index 0000000..a6d580d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib.class
new file mode 100644
index 0000000..046aecf
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryResourceTagLib.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure1.class
new file mode 100644
index 0000000..7efbb2e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure2.class
new file mode 100644
index 0000000..58207ca
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure3.class
new file mode 100644
index 0000000..768c298
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure4.class
new file mode 100644
index 0000000..e39adca
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService.class
new file mode 100644
index 0000000..12e5acb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryService.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure1.class
new file mode 100644
index 0000000..ca5192b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure1_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure1_closure6.class
new file mode 100644
index 0000000..1aed11e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure1_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure2.class
new file mode 100644
index 0000000..f325123
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure3.class
new file mode 100644
index 0000000..f70151b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure4.class
new file mode 100644
index 0000000..e1e5990
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure5.class
new file mode 100644
index 0000000..2eb1472
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib$_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib.class b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib.class
new file mode 100644
index 0000000..193c302
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/JQueryTagLib.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure1.class
new file mode 100644
index 0000000..98f2a7d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure2.class
new file mode 100644
index 0000000..1a44059
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure3.class
new file mode 100644
index 0000000..cadfdc8
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure4.class
new file mode 100644
index 0000000..b4390a2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure5.class
new file mode 100644
index 0000000..967fbbd
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure6.class
new file mode 100644
index 0000000..4d5531d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure7.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure7.class
new file mode 100644
index 0000000..f31a779
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure7.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure8.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure8.class
new file mode 100644
index 0000000..5c62a01
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController$_closure8.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LoginController.class b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController.class
new file mode 100644
index 0000000..0ed734b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LoginController.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LogoutController$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/LogoutController$_closure1.class
new file mode 100644
index 0000000..a7cee34
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LogoutController$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/LogoutController.class b/ch09/ch10/demo-grails/target-eclipse/classes/LogoutController.class
new file mode 100644
index 0000000..df5e9de
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/LogoutController.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap$_closure1.class
new file mode 100644
index 0000000..390aa1b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap$_closure2.class
new file mode 100644
index 0000000..799885a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap.class b/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap.class
new file mode 100644
index 0000000..61148e7
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/ResourcesBootStrap.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1.class
new file mode 100644
index 0000000..d56294c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1_closure2.class
new file mode 100644
index 0000000..698c0e1
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1_closure2_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1_closure2_closure3.class
new file mode 100644
index 0000000..7790789
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings$__clinit__closure1_closure2_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings.class b/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings.class
new file mode 100644
index 0000000..252f32b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/UrlMappings.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_globalnav.gsp b/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_globalnav.gsp
new file mode 100644
index 0000000..639dd04
--- /dev/null
+++ b/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_globalnav.gsp
@@ -0,0 +1,24 @@
+
+
+
+Overview
+
+
+
+
+
+Current Tables
+
+Authors
+
+Change Logs
+
+Pending Changes
+
+Pending SQL
+
+Most Recent Changes
+
+
+
+
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_index.gsp b/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_index.gsp
new file mode 100644
index 0000000..f24929a
--- /dev/null
+++ b/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_index.gsp
@@ -0,0 +1,22 @@
+
+
+
+Database Documentation
+
+
+
+
+
+
+
+
+
+Frame Alert
+
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+
+Link toNon-frame version.
+
+
+
+
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_overview-summary.gsp b/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_overview-summary.gsp
new file mode 100644
index 0000000..8f201a1
--- /dev/null
+++ b/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_overview-summary.gsp
@@ -0,0 +1,11 @@
+
+
+ Database Documentation Overview
+
+
+
+ Database Documentation
+ This report contains documentation on the database changes made.
+ Use the navigation to the left to navigate the documentation.
+
+
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_stylesheet.gsp b/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_stylesheet.gsp
new file mode 100644
index 0000000..e512032
--- /dev/null
+++ b/ch09/ch10/demo-grails/target-eclipse/classes/dbdoc/_stylesheet.gsp
@@ -0,0 +1,60 @@
+h1 {
+}
+
+.TableHeadingColor {
+ background: #ccccff; /* Dark mauve */
+}
+.TableSubHeadingColor {
+ background: #eeeeff; /* Light mauve */
+}
+.TableRowColor {
+ background: white;
+}
+
+.NavBarCell1 {
+ background-color: #eeeeff; /* Light mauve */
+}
+.NavBarCell1Rev {
+ background-color: #00008b; /* Dark Blue */
+}
+.NavBarFont1 {
+ color: black;
+}
+.NavBarFont1Rev {
+ color: white;
+}
+
+.NavBarCell2 {
+ background-color: white;
+}
+.NavBarCell3 {
+ background-color: white;
+}
+
+body {
+ background: #fff;
+ color: #333;
+ font: 12px verdana, arial, helvetica, sans-serif;
+}
+
+a:link, a:visited, a:hover {
+ color: #666;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+td, th {
+ font: 11px verdana, arial, helvetica, sans-serif;
+ line-height: 12px;
+ padding: 5px 6px;
+ text-align: left;
+ vertical-align: top;
+}
+
+th {
+ color: #666;
+ font-size: 11px;
+ font-weight: bold;
+ line-height: 17px;
+ padding: 2px 6px;
+}
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/SecuredController.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/SecuredController.class
new file mode 100644
index 0000000..243fc19
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/SecuredController.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/SecuredControllerTests.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/SecuredControllerTests.class
new file mode 100644
index 0000000..e6a2ee5
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/SecuredControllerTests.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/UnsecuredController.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/UnsecuredController.class
new file mode 100644
index 0000000..c5999b6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/UnsecuredController.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/UnsecuredControllerTests.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/UnsecuredControllerTests.class
new file mode 100644
index 0000000..036ba93
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/grails/UnsecuredControllerTests.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role$__clinit__closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role$__clinit__closure1.class
new file mode 100644
index 0000000..286a81a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role$__clinit__closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role$__clinit__closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role$__clinit__closure2.class
new file mode 100644
index 0000000..a60fc95
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role$__clinit__closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role.class
new file mode 100644
index 0000000..e030edb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/Role.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$__clinit__closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$__clinit__closure2.class
new file mode 100644
index 0000000..0a445e5
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$__clinit__closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$__clinit__closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$__clinit__closure3.class
new file mode 100644
index 0000000..510d53b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$__clinit__closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$_getAuthorities_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$_getAuthorities_closure1.class
new file mode 100644
index 0000000..7365690
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User$_getAuthorities_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User.class
new file mode 100644
index 0000000..5cbbc13
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/User.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/UserRole$__clinit__closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/UserRole$__clinit__closure1.class
new file mode 100644
index 0000000..fbd826f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/UserRole$__clinit__closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/UserRole.class b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/UserRole.class
new file mode 100644
index 0000000..16445ac
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/demo/security/UserRole.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/BlockingCache.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/BlockingCache.class
new file mode 100644
index 0000000..57cd2c1
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/BlockingCache.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheBeanPostProcessor.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheBeanPostProcessor.class
new file mode 100644
index 0000000..36aeed1
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheBeanPostProcessor.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler$CacheConfigGrailsClass.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler$CacheConfigGrailsClass.class
new file mode 100644
index 0000000..1298b97
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler$CacheConfigGrailsClass.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler$DefaultCacheConfigGrailsClass.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler$DefaultCacheConfigGrailsClass.class
new file mode 100644
index 0000000..2991b4c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler$DefaultCacheConfigGrailsClass.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler.class
new file mode 100644
index 0000000..224f752
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfigArtefactHandler.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfiguration.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfiguration.class
new file mode 100644
index 0000000..9696d9c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheConfiguration.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheEvict.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheEvict.class
new file mode 100644
index 0000000..abdbb9c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheEvict.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CachePut.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CachePut.class
new file mode 100644
index 0000000..725825e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CachePut.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib$_closure1.class
new file mode 100644
index 0000000..3d812e4
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib$_closure2.class
new file mode 100644
index 0000000..ff1922c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib.class
new file mode 100644
index 0000000..a2e2445
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/CacheTagLib.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/Cacheable.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/Cacheable.class
new file mode 100644
index 0000000..a0b73b5
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/Cacheable.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigBuilder.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigBuilder.class
new file mode 100644
index 0000000..58b7204
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigBuilder.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigLoader$_sortConfigs_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigLoader$_sortConfigs_closure1.class
new file mode 100644
index 0000000..d5ca968
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigLoader$_sortConfigs_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigLoader.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigLoader.class
new file mode 100644
index 0000000..5ac4cef
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/ConfigLoader.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource$DefaultCacheKey.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource$DefaultCacheKey.class
new file mode 100644
index 0000000..f2c3107
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource$DefaultCacheKey.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource.class
new file mode 100644
index 0000000..97a0065
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCache.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCache.class
new file mode 100644
index 0000000..3b2e5b2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCache.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCacheAdminService.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCacheAdminService.class
new file mode 100644
index 0000000..51cb079
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCacheAdminService.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCacheManager.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCacheManager.class
new file mode 100644
index 0000000..8de4d3c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsCacheManager.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsConcurrentMapCache.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsConcurrentMapCache.class
new file mode 100644
index 0000000..6bb1c1b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsConcurrentMapCache.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsConcurrentMapCacheManager.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsConcurrentMapCacheManager.class
new file mode 100644
index 0000000..289dd53
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsConcurrentMapCacheManager.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsValueWrapper.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsValueWrapper.class
new file mode 100644
index 0000000..09b5d04
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/GrailsValueWrapper.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/SerializableByteArrayOutputStream.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/SerializableByteArrayOutputStream.class
new file mode 100644
index 0000000..cc6d65f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/SerializableByteArrayOutputStream.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/SerializableOutputStream.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/SerializableOutputStream.class
new file mode 100644
index 0000000..7d06eff
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/SerializableOutputStream.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/Timer.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/Timer.class
new file mode 100644
index 0000000..3a3483b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/Timer.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/compiler/CacheTransformation.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/compiler/CacheTransformation.class
new file mode 100644
index 0000000..fd4e4d8
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/compiler/CacheTransformation.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/util/ClassUtils.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/util/ClassUtils.class
new file mode 100644
index 0000000..ed927fe
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/util/ClassUtils.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/AlreadyGzippedException.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/AlreadyGzippedException.class
new file mode 100644
index 0000000..59cc420
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/AlreadyGzippedException.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/ContentCacheParameters.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/ContentCacheParameters.class
new file mode 100644
index 0000000..a8be1f9
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/ContentCacheParameters.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/GenericResponseWrapper.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/GenericResponseWrapper.class
new file mode 100644
index 0000000..02ecd01
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/GenericResponseWrapper.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/Header$Type.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/Header$Type.class
new file mode 100644
index 0000000..0fdfb62
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/Header$Type.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/Header.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/Header.class
new file mode 100644
index 0000000..b61574b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/Header.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/HttpDateFormatter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/HttpDateFormatter.class
new file mode 100644
index 0000000..55ca636
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/HttpDateFormatter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/PageInfo.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/PageInfo.class
new file mode 100644
index 0000000..5df6cef
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/PageInfo.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/ProxyAwareMixedGrailsControllerHelper.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/ProxyAwareMixedGrailsControllerHelper.class
new file mode 100644
index 0000000..f8718ef
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/ProxyAwareMixedGrailsControllerHelper.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/SerializableCookie.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/SerializableCookie.class
new file mode 100644
index 0000000..62069b1
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/SerializableCookie.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/AbstractFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/AbstractFilter.class
new file mode 100644
index 0000000..45e7702
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/AbstractFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/CacheExpressionRootObject.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/CacheExpressionRootObject.class
new file mode 100644
index 0000000..d0bef7b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/CacheExpressionRootObject.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/CacheOperationContext.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/CacheOperationContext.class
new file mode 100644
index 0000000..2c55e50
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/CacheOperationContext.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/DefaultWebKeyGenerator.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/DefaultWebKeyGenerator.class
new file mode 100644
index 0000000..dbb6f87
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/DefaultWebKeyGenerator.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/ExpressionEvaluator.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/ExpressionEvaluator.class
new file mode 100644
index 0000000..6778ae0
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/ExpressionEvaluator.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/FilterServletOutputStream.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/FilterServletOutputStream.class
new file mode 100644
index 0000000..4d2f384
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/FilterServletOutputStream.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/LazyParamAwareEvaluationContext.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/LazyParamAwareEvaluationContext.class
new file mode 100644
index 0000000..a5c5dd4
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/LazyParamAwareEvaluationContext.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/NoOpFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/NoOpFilter.class
new file mode 100644
index 0000000..b0d5ce9
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/NoOpFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$1.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$1.class
new file mode 100644
index 0000000..5561dc2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$CacheStatus.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$CacheStatus.class
new file mode 100644
index 0000000..87f4e17
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$CacheStatus.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter.class
new file mode 100644
index 0000000..711d0eb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/WebKeyGenerator.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/WebKeyGenerator.class
new file mode 100644
index 0000000..2defc5b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/WebKeyGenerator.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryBlockingCache.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryBlockingCache.class
new file mode 100644
index 0000000..075c3b9
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryBlockingCache.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryCacheConfiguration.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryCacheConfiguration.class
new file mode 100644
index 0000000..e05f7c0
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryCacheConfiguration.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryPageFragmentCachingFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryPageFragmentCachingFilter.class
new file mode 100644
index 0000000..1f87ac6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/cache/web/filter/simple/MemoryPageFragmentCachingFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendAttrs_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendAttrs_closure1.class
new file mode 100644
index 0000000..2f69788
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendAttrs_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendWithIndent_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendWithIndent_closure2.class
new file mode 100644
index 0000000..3906b50
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendWithIndent_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy.class
new file mode 100644
index 0000000..0d2e351
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/ChangelogXml2Groovy.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/MigrationRunner$_autoRun_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/MigrationRunner$_autoRun_closure1.class
new file mode 100644
index 0000000..1b7a8af
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/MigrationRunner$_autoRun_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/MigrationRunner.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/MigrationRunner.class
new file mode 100644
index 0000000..1196937
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/MigrationRunner.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/AuthorListWriter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/AuthorListWriter.class
new file mode 100644
index 0000000..29b45b9
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/AuthorListWriter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/ChangeLogListWriter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/ChangeLogListWriter.class
new file mode 100644
index 0000000..5422346
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/ChangeLogListWriter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/HTMLListWriter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/HTMLListWriter.class
new file mode 100644
index 0000000..6da2566
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/HTMLListWriter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/TableListWriter.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/TableListWriter.class
new file mode 100644
index 0000000..494d084
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugin/databasemigration/dbdoc/TableListWriter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/BCryptPasswordEncoder.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/BCryptPasswordEncoder.class
new file mode 100644
index 0000000..e4a3f2d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/BCryptPasswordEncoder.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/DigestAuthPasswordEncoder.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/DigestAuthPasswordEncoder.class
new file mode 100644
index 0000000..c6e502b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/DigestAuthPasswordEncoder.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/Secured.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/Secured.class
new file mode 100644
index 0000000..cb5abdb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/Secured.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityConfigType.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityConfigType.class
new file mode 100644
index 0000000..8a6ba81
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityConfigType.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$__clinit__closure13.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$__clinit__closure13.class
new file mode 100644
index 0000000..0e79241
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$__clinit__closure13.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure1.class
new file mode 100644
index 0000000..7e38d07
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure10.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure10.class
new file mode 100644
index 0000000..5fc755b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure10.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure11.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure11.class
new file mode 100644
index 0000000..e64a8cc
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure11.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure12.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure12.class
new file mode 100644
index 0000000..ce5330a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure12.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure2.class
new file mode 100644
index 0000000..b65a282
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure3.class
new file mode 100644
index 0000000..f8e740c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure4.class
new file mode 100644
index 0000000..e876359
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure5.class
new file mode 100644
index 0000000..69a0bfb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure6.class
new file mode 100644
index 0000000..694c70c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure7.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure7.class
new file mode 100644
index 0000000..563350f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure7.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure8.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure8.class
new file mode 100644
index 0000000..2a10622
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure8.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure9.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure9.class
new file mode 100644
index 0000000..b64cfe2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib$_closure9.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib.class
new file mode 100644
index 0000000..edea32e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SecurityTagLib.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SpringSecurityService$_deleteRole_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SpringSecurityService$_deleteRole_closure1.class
new file mode 100644
index 0000000..6c8d7c4
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SpringSecurityService$_deleteRole_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SpringSecurityService.class b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SpringSecurityService.class
new file mode 100644
index 0000000..dd4749a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/grails/plugins/springsecurity/SpringSecurityService.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/messages.properties b/ch09/ch10/demo-grails/target-eclipse/classes/messages.properties
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure1.class
new file mode 100644
index 0000000..71186e6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure2.class
new file mode 100644
index 0000000..7ec2658
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig.class
new file mode 100644
index 0000000..18b0679
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure1.class
new file mode 100644
index 0000000..1533d8f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure2.class
new file mode 100644
index 0000000..05ee858
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure3.class
new file mode 100644
index 0000000..2a46a00
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure4.class
new file mode 100644
index 0000000..3dc9b3a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider.class
new file mode 100644
index 0000000..86e3087
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AbstractFilterInvocationDefinition.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AbstractFilterInvocationDefinition.class
new file mode 100644
index 0000000..ca757ee
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AbstractFilterInvocationDefinition.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAccessDeniedHandler.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAccessDeniedHandler.class
new file mode 100644
index 0000000..4d217fe
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAccessDeniedHandler.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationEntryPoint.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationEntryPoint.class
new file mode 100644
index 0000000..cd9bd92
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationEntryPoint.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationFailureHandler.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationFailureHandler.class
new file mode 100644
index 0000000..84a57f2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationFailureHandler.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationSuccessHandler.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationSuccessHandler.class
new file mode 100644
index 0000000..90a6a94
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationSuccessHandler.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AnnotationFilterInvocationDefinition.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AnnotationFilterInvocationDefinition.class
new file mode 100644
index 0000000..8927630
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AnnotationFilterInvocationDefinition.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AuthenticatedVetoableDecisionManager.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AuthenticatedVetoableDecisionManager.class
new file mode 100644
index 0000000..3473981
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/AuthenticatedVetoableDecisionManager.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ChannelFilterInvocationSecurityMetadataSourceFactoryBean.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ChannelFilterInvocationSecurityMetadataSourceFactoryBean.class
new file mode 100644
index 0000000..83decca
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ChannelFilterInvocationSecurityMetadataSourceFactoryBean.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPostAuthenticationChecks.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPostAuthenticationChecks.class
new file mode 100644
index 0000000..24660e0
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPostAuthenticationChecks.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPreAuthenticationChecks.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPreAuthenticationChecks.class
new file mode 100644
index 0000000..43efffa
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPreAuthenticationChecks.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator$1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator$1.class
new file mode 100644
index 0000000..fa52135
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator$1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator.class
new file mode 100644
index 0000000..35a3875
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator$1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator$1.class
new file mode 100644
index 0000000..a321bd5
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator$1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator.class
new file mode 100644
index 0000000..1a1b23a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_createNewToken_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_createNewToken_closure1.class
new file mode 100644
index 0000000..1850d34
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_createNewToken_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_removeUserTokens_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_removeUserTokens_closure2.class
new file mode 100644
index 0000000..9e0f4fc
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_removeUserTokens_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_updateToken_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_updateToken_closure3.class
new file mode 100644
index 0000000..2d82658
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_updateToken_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository.class
new file mode 100644
index 0000000..70442ec
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadAuthorities_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadAuthorities_closure2.class
new file mode 100644
index 0000000..e195a64
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadAuthorities_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadUserByUsername_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadUserByUsername_closure1.class
new file mode 100644
index 0000000..b9e59cf
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadUserByUsername_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService.class
new file mode 100644
index 0000000..582a757
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUser.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUser.class
new file mode 100644
index 0000000..69a6c26
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUser.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUserDetailsService.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUserDetailsService.class
new file mode 100644
index 0000000..e90f8ac
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUserDetailsService.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator$1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator$1.class
new file mode 100644
index 0000000..26d651c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator$1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator.class
new file mode 100644
index 0000000..5cb53a3
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckInsecureChannelProcessor.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckInsecureChannelProcessor.class
new file mode 100644
index 0000000..a68677e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckInsecureChannelProcessor.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckSecureChannelProcessor.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckSecureChannelProcessor.class
new file mode 100644
index 0000000..0dafb9c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckSecureChannelProcessor.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/InterceptUrlMapFilterInvocationDefinition.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/InterceptUrlMapFilterInvocationDefinition.class
new file mode 100644
index 0000000..e8e8eef
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/InterceptUrlMapFilterInvocationDefinition.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/IpAddressFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/IpAddressFilter.class
new file mode 100644
index 0000000..6b55794
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/IpAddressFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter$DummyLogoutHandler.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter$DummyLogoutHandler.class
new file mode 100644
index 0000000..2442281
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter$DummyLogoutHandler.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter.class
new file mode 100644
index 0000000..01efc04
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullAuthenticationEventPublisher.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullAuthenticationEventPublisher.class
new file mode 100644
index 0000000..78e09ea
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullAuthenticationEventPublisher.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullLogoutHandlerRememberMeServices.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullLogoutHandlerRememberMeServices.class
new file mode 100644
index 0000000..ee0df90
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullLogoutHandlerRememberMeServices.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullSaltSource.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullSaltSource.class
new file mode 100644
index 0000000..1274423
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullSaltSource.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils$_splitMap_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils$_splitMap_closure1.class
new file mode 100644
index 0000000..fb80777
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils$_splitMap_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils.class
new file mode 100644
index 0000000..7c16281
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestHolderAuthenticationFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestHolderAuthenticationFilter.class
new file mode 100644
index 0000000..e57d267
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestHolderAuthenticationFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestmapFilterInvocationDefinition.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestmapFilterInvocationDefinition.class
new file mode 100644
index 0000000..10e4518
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestmapFilterInvocationDefinition.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityEventListener.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityEventListener.class
new file mode 100644
index 0000000..298ee3f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityEventListener.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityFilterPosition.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityFilterPosition.class
new file mode 100644
index 0000000..48c2a77
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityFilterPosition.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityRequestHolder.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityRequestHolder.class
new file mode 100644
index 0000000..a0ed74d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityRequestHolder.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils$1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils$1.class
new file mode 100644
index 0000000..1ec0ecb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils$1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils.class
new file mode 100644
index 0000000..cb82c3e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionConfigAttribute.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionConfigAttribute.class
new file mode 100644
index 0000000..9d078d6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionConfigAttribute.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionVoter.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionVoter.class
new file mode 100644
index 0000000..1d0bb19
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionVoter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3.class
new file mode 100644
index 0000000..abeca0f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3_closure4.class
new file mode 100644
index 0000000..7fce905
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_containsResource_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_containsResource_closure1.class
new file mode 100644
index 0000000..349ae1a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_containsResource_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_isDirty_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_isDirty_closure2.class
new file mode 100644
index 0000000..72ed819
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta$_isDirty_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta.class
new file mode 100644
index 0000000..d1f75fc
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/AggregatedResourceMeta.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/BundleResourceMapper.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/BundleResourceMapper.class
new file mode 100644
index 0000000..88b884e
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/BundleResourceMapper.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSBundleResourceMeta.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSBundleResourceMeta.class
new file mode 100644
index 0000000..ccdf163
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSBundleResourceMeta.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSLinkProcessor$_process_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSLinkProcessor$_process_closure1.class
new file mode 100644
index 0000000..4a647f9
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSLinkProcessor$_process_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSLinkProcessor.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSLinkProcessor.class
new file mode 100644
index 0000000..90085cc
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSLinkProcessor.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper$_map_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper$_map_closure1.class
new file mode 100644
index 0000000..c06ce35
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper$_map_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper.class
new file mode 100644
index 0000000..7c65637
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1.class
new file mode 100644
index 0000000..24f3fc2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1_closure2.class
new file mode 100644
index 0000000..8c5c459
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper.class
new file mode 100644
index 0000000..e7a971f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/CSSRewriterResourceMapper.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/DevModeSanityFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/DevModeSanityFilter.class
new file mode 100644
index 0000000..6b52ea0
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/DevModeSanityFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/JavaScriptBundleResourceMeta.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/JavaScriptBundleResourceMeta.class
new file mode 100644
index 0000000..2f6b46f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/JavaScriptBundleResourceMeta.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ProcessingFilter.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ProcessingFilter.class
new file mode 100644
index 0000000..2ccfd63
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ProcessingFilter.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceMeta$_reset_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceMeta$_reset_closure1.class
new file mode 100644
index 0000000..f7cc850
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceMeta$_reset_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceMeta.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceMeta.class
new file mode 100644
index 0000000..18ea8b8
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceMeta.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_closure1.class
new file mode 100644
index 0000000..9910dcf
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_getRequiredDispositions_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_getRequiredDispositions_closure3.class
new file mode 100644
index 0000000..d695e2f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_getRequiredDispositions_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_newResourceFromArgs_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_newResourceFromArgs_closure2.class
new file mode 100644
index 0000000..0356953
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule$_newResourceFromArgs_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule.class
new file mode 100644
index 0000000..8265d97
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceModule.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure5.class
new file mode 100644
index 0000000..18ce674
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure6.class
new file mode 100644
index 0000000..dcbe611
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure7.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure7.class
new file mode 100644
index 0000000..f560728
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure7.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure8.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure8.class
new file mode 100644
index 0000000..ed0ad15
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure8.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_defineModuleFromBuilder_closure16.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_defineModuleFromBuilder_closure16.class
new file mode 100644
index 0000000..59c2293
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_defineModuleFromBuilder_closure16.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21.class
new file mode 100644
index 0000000..428503c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure35.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure35.class
new file mode 100644
index 0000000..e704518
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure35.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure36.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure36.class
new file mode 100644
index 0000000..bfd4d9b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure36.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure22.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure22.class
new file mode 100644
index 0000000..492c46c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure22.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20.class
new file mode 100644
index 0000000..5062403
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20_closure34.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20_closure34.class
new file mode 100644
index 0000000..53c68ea
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20_closure34.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_findSyntheticResourceById_closure9.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_findSyntheticResourceById_closure9.class
new file mode 100644
index 0000000..226ec03
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_findSyntheticResourceById_closure9.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getConfigParamOrDefault_closure23.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getConfigParamOrDefault_closure23.class
new file mode 100644
index 0000000..0962770
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getConfigParamOrDefault_closure23.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10.class
new file mode 100644
index 0000000..af7b173
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10_closure27.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10_closure27.class
new file mode 100644
index 0000000..eeca60c
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10_closure27.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getServletContext_closure24.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getServletContext_closure24.class
new file mode 100644
index 0000000..45881f8
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_getServletContext_closure24.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure17.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure17.class
new file mode 100644
index 0000000..c101f1f
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure17.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18.class
new file mode 100644
index 0000000..646d1c6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure30.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure30.class
new file mode 100644
index 0000000..3eab1b6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure30.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31.class
new file mode 100644
index 0000000..44d6236
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure32.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure32.class
new file mode 100644
index 0000000..ca76555
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure32.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure33.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure33.class
new file mode 100644
index 0000000..10b6b54
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure33.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure19.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure19.class
new file mode 100644
index 0000000..c67a2d9
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure19.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_makeFileSystemPathFromURI_closure11.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_makeFileSystemPathFromURI_closure11.class
new file mode 100644
index 0000000..f9e9a45
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_makeFileSystemPathFromURI_closure11.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure13.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure13.class
new file mode 100644
index 0000000..4a58911
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure13.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14.class
new file mode 100644
index 0000000..a524e65
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure28.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure28.class
new file mode 100644
index 0000000..f133c71
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure28.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure29.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure29.class
new file mode 100644
index 0000000..e7b1fd8
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure29.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure15.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure15.class
new file mode 100644
index 0000000..ede0710
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure15.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareSingleDeclaredResource_closure12.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareSingleDeclaredResource_closure12.class
new file mode 100644
index 0000000..503318a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_prepareSingleDeclaredResource_closure12.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure1.class
new file mode 100644
index 0000000..aebb653
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure2.class
new file mode 100644
index 0000000..b161b88
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3.class
new file mode 100644
index 0000000..a8fa484
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3_closure25.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3_closure25.class
new file mode 100644
index 0000000..9afefc6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3_closure25.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4.class
new file mode 100644
index 0000000..73be28d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4_closure26.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4_closure26.class
new file mode 100644
index 0000000..35301b2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4_closure26.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor.class
new file mode 100644
index 0000000..8ac30e3
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessor.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessorBatch.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessorBatch.class
new file mode 100644
index 0000000..6e6b624
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceProcessorBatch.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure13.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure13.class
new file mode 100644
index 0000000..f608841
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure13.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure14.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure14.class
new file mode 100644
index 0000000..2f9683d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure14.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure1.class
new file mode 100644
index 0000000..d4a8dce
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure10.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure10.class
new file mode 100644
index 0000000..160f343
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure10.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure10_closure17.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure10_closure17.class
new file mode 100644
index 0000000..962724b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure10_closure17.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure1_closure15.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure1_closure15.class
new file mode 100644
index 0000000..5e28fba
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure1_closure15.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure2.class
new file mode 100644
index 0000000..8f6eaec
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure3.class
new file mode 100644
index 0000000..0164c9d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure4.class
new file mode 100644
index 0000000..250e081
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure5.class
new file mode 100644
index 0000000..305243a
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure5_closure16.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure5_closure16.class
new file mode 100644
index 0000000..dbef601
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure5_closure16.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure6.class
new file mode 100644
index 0000000..5bff82b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure7.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure7.class
new file mode 100644
index 0000000..0b81156
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure7.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure8.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure8.class
new file mode 100644
index 0000000..9950c34
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure8.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure9.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure9.class
new file mode 100644
index 0000000..f93febd
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_closure9.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_resolveResourceAndURI_closure12.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_resolveResourceAndURI_closure12.class
new file mode 100644
index 0000000..fe5ff3b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_resolveResourceAndURI_closure12.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_writeAttrs_closure11.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_writeAttrs_closure11.class
new file mode 100644
index 0000000..4060472
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib$_writeAttrs_closure11.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib.class
new file mode 100644
index 0000000..d5330bc
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/ResourceTagLib.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/URLUtils.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/URLUtils.class
new file mode 100644
index 0000000..2d66530
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/URLUtils.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/MapperPhase.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/MapperPhase.class
new file mode 100644
index 0000000..8e97f72
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/MapperPhase.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_closure1.class
new file mode 100644
index 0000000..1371db6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultExcludes_closure8.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultExcludes_closure8.class
new file mode 100644
index 0000000..6bed3c5
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultExcludes_closure8.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultIncludes_closure9.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultIncludes_closure9.class
new file mode 100644
index 0000000..277a047
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultIncludes_closure9.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludes_closure10.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludes_closure10.class
new file mode 100644
index 0000000..68bee10
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludes_closure10.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludingPattern_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludingPattern_closure2.class
new file mode 100644
index 0000000..ba26e31
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludingPattern_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludes_closure11.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludes_closure11.class
new file mode 100644
index 0000000..c3b109b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludes_closure11.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludingPattern_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludingPattern_closure3.class
new file mode 100644
index 0000000..fea29ac
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludingPattern_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getName_closure7.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getName_closure7.class
new file mode 100644
index 0000000..a046e54
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getName_closure7.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getOperation_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getOperation_closure5.class
new file mode 100644
index 0000000..4c37e76
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getOperation_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPhase_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPhase_closure4.class
new file mode 100644
index 0000000..83511ea
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPhase_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPriority_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPriority_closure6.class
new file mode 100644
index 0000000..2f2d6e0
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPriority_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper.class
new file mode 100644
index 0000000..52b220d
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMapper.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure1.class
new file mode 100644
index 0000000..67a8d35
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2.class
new file mode 100644
index 0000000..5e6a2b7
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2_closure7.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2_closure7.class
new file mode 100644
index 0000000..bd6b6c7
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2_closure7.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure3.class
new file mode 100644
index 0000000..1737be7
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure4.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure4.class
new file mode 100644
index 0000000..0ee6266
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure4.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure5.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure5.class
new file mode 100644
index 0000000..f573017
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure5.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure6.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure6.class
new file mode 100644
index 0000000..a2eb189
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure6.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory.class
new file mode 100644
index 0000000..a970bb9
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleBuilder.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleBuilder.class
new file mode 100644
index 0000000..8bd78cb
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleBuilder.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure1.class
new file mode 100644
index 0000000..9efc233
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure2.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure2.class
new file mode 100644
index 0000000..28844d8
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure2.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure3.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure3.class
new file mode 100644
index 0000000..f8b9ac2
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure3.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory.class
new file mode 100644
index 0000000..a1adf63
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModulesBuilder$_invokeMethod_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModulesBuilder$_invokeMethod_closure1.class
new file mode 100644
index 0000000..c073429
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModulesBuilder$_invokeMethod_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModulesBuilder.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModulesBuilder.class
new file mode 100644
index 0000000..715bd37
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/module/ModulesBuilder.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/HalfBakedLegacyLinkGenerator.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/HalfBakedLegacyLinkGenerator.class
new file mode 100644
index 0000000..9abca2b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/HalfBakedLegacyLinkGenerator.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/ResourceMetaStore$_addResource_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/ResourceMetaStore$_addResource_closure1.class
new file mode 100644
index 0000000..9b9bcee
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/ResourceMetaStore$_addResource_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/ResourceMetaStore.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/ResourceMetaStore.class
new file mode 100644
index 0000000..8fad0c7
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resource/util/ResourceMetaStore.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/AbstractResourcesArtefactHandler.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/AbstractResourcesArtefactHandler.class
new file mode 100644
index 0000000..77451f6
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/AbstractResourcesArtefactHandler.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/DefaultResourceMapperClass.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/DefaultResourceMapperClass.class
new file mode 100644
index 0000000..6b6a140
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/DefaultResourceMapperClass.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/DefaultResourcesClass.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/DefaultResourcesClass.class
new file mode 100644
index 0000000..9720ee0
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/DefaultResourcesClass.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourceMapperArtefactHandler.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourceMapperArtefactHandler.class
new file mode 100644
index 0000000..d8e2add
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourceMapperArtefactHandler.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourceMapperClass.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourceMapperClass.class
new file mode 100644
index 0000000..4c6e3a1
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourceMapperClass.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourcesArtefactHandler.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourcesArtefactHandler.class
new file mode 100644
index 0000000..5f3562b
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourcesArtefactHandler.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourcesClass.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourcesClass.class
new file mode 100644
index 0000000..5a344ff
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/grails/plugin/resources/artefacts/ResourcesClass.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/org/mindrot/jbcrypt/BCrypt.class b/ch09/ch10/demo-grails/target-eclipse/classes/org/mindrot/jbcrypt/BCrypt.class
new file mode 100644
index 0000000..cf0e1b5
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/org/mindrot/jbcrypt/BCrypt.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/resources$_run_closure1.class b/ch09/ch10/demo-grails/target-eclipse/classes/resources$_run_closure1.class
new file mode 100644
index 0000000..62321cd
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/resources$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/resources.class b/ch09/ch10/demo-grails/target-eclipse/classes/resources.class
new file mode 100644
index 0000000..b7b8fe8
Binary files /dev/null and b/ch09/ch10/demo-grails/target-eclipse/classes/resources.class differ
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core.properties b/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core.properties
new file mode 100644
index 0000000..13fdc56
--- /dev/null
+++ b/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core.properties
@@ -0,0 +1,18 @@
+# Login errors
+springSecurity.errors.login.expired=Sorry, your account has expired.
+springSecurity.errors.login.passwordExpired=Sorry, your password has expired.
+springSecurity.errors.login.disabled=Sorry, your account is disabled.
+springSecurity.errors.login.locked=Sorry, your account is locked.
+springSecurity.errors.login.fail=Sorry, we were not able to find a user with that username and password.
+
+# Login Page
+springSecurity.login.title=Login
+springSecurity.login.header=Please Login
+springSecurity.login.button=Login
+springSecurity.login.username.label=Username
+springSecurity.login.password.label=Password
+springSecurity.login.remember.me.label=Remember me
+
+# Denied Page
+springSecurity.denied.title=Denied
+springSecurity.denied.message=Sorry, you're not authorized to view this page.
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core_de.properties b/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core_de.properties
new file mode 100644
index 0000000..b237c43
--- /dev/null
+++ b/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core_de.properties
@@ -0,0 +1,18 @@
+# Login errors
+springSecurity.errors.login.expired=Die Gltigkeit ihres Zugangs ist leider abgelaufen.
+springSecurity.errors.login.passwordExpire=Die Gltigkeit ihres Passwortes ist leider abgelaufen.
+springSecurity.errors.login.disabled=Ihr Zugang wurde leider deaktiviert.
+springSecurity.errors.login.locked=Ihr Zugang wurde leider gesperrt.
+springSecurity.errors.login.fail=Es konnte leider kein Zugang mit dem entsprechenden Benutzernamen und Passwort gefunden werden.
+
+# Login Page
+springSecurity.login.title=Anmeldung
+springSecurity.login.header=Bitte anmelden
+springSecurity.login.button=Anmelden
+springSecurity.login.username.label=Benutzername
+springSecurity.login.password.label=Passwort
+springSecurity.login.remember.me.label=Angemeldet bleiben
+
+# Denied Page
+springSecurity.denied.title=Zugriff abgelehnt
+springSecurity.denied.message=Sie sind leider nicht dazu berechtigt, diese Seite zu betrachten.
diff --git a/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core_fr.properties b/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core_fr.properties
new file mode 100644
index 0000000..b2d37d4
--- /dev/null
+++ b/ch09/ch10/demo-grails/target-eclipse/classes/spring-security-core_fr.properties
@@ -0,0 +1,18 @@
+# Login errors
+springSecurity.errors.login.expired=Dsol, votre compte a expir.
+springSecurity.errors.login.passwordExpired=Dsol, votre mot de passe a expir.
+springSecurity.errors.login.disabled=Dsol, votre compte est dsactiv.
+springSecurity.errors.login.locked=Dsol, votre compte est vrouill.
+springSecurity.errors.login.fail=Dsol, nous n'avons pas pu trouver d'utilisateur avec ce login et ce mot de passe.
+
+# Login Page
+springSecurity.login.title=Login
+springSecurity.login.header=Connectez-vous l'aide de vos identifiants
+springSecurity.login.button=Connexion
+springSecurity.login.username.label=Nom d'utilisateur
+springSecurity.login.password.label=Mot de passe
+springSecurity.login.remember.me.label=Rester connect
+
+# Denied Page
+springSecurity.denied.title=Accs refus
+springSecurity.denied.message=Dsol, vous n'tes pas autoriss accder cette page.
diff --git a/ch09/ch10/demo-grails/test/unit/demo/grails/SecuredControllerTests.groovy b/ch09/ch10/demo-grails/test/unit/demo/grails/SecuredControllerTests.groovy
new file mode 100644
index 0000000..eeed0c9
--- /dev/null
+++ b/ch09/ch10/demo-grails/test/unit/demo/grails/SecuredControllerTests.groovy
@@ -0,0 +1,17 @@
+package demo.grails
+
+
+
+import grails.test.mixin.*
+import org.junit.*
+
+/**
+ * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
+ */
+@TestFor(SecuredController)
+class SecuredControllerTests {
+
+ void testSomething() {
+ fail "Implement me"
+ }
+}
diff --git a/ch09/ch10/demo-grails/test/unit/demo/grails/UnsecuredControllerTests.groovy b/ch09/ch10/demo-grails/test/unit/demo/grails/UnsecuredControllerTests.groovy
new file mode 100644
index 0000000..8d270bc
--- /dev/null
+++ b/ch09/ch10/demo-grails/test/unit/demo/grails/UnsecuredControllerTests.groovy
@@ -0,0 +1,17 @@
+package demo.grails
+
+
+
+import grails.test.mixin.*
+import org.junit.*
+
+/**
+ * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
+ */
+@TestFor(UnsecuredController)
+class UnsecuredControllerTests {
+
+ void testSomething() {
+ fail "Implement me"
+ }
+}
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/applicationContext.xml b/ch09/ch10/demo-grails/web-app/WEB-INF/applicationContext.xml
new file mode 100644
index 0000000..69fbef3
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/applicationContext.xml
@@ -0,0 +1,33 @@
+
+
+
+
+ Grails application factory bean
+
+
+
+
+
+ A bean that manages Grails plugins
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ utf-8
+
+
+
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources$_run_closure1.class
new file mode 100644
index 0000000..bbb497f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources$_run_closure1_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources$_run_closure1_closure2.class
new file mode 100644
index 0000000..caba913
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources$_run_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources.class
new file mode 100644
index 0000000..24c6376
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ApplicationResources.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap$_closure1.class
new file mode 100644
index 0000000..13c8ce9
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap$_closure2.class
new file mode 100644
index 0000000..040e67b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap.class
new file mode 100644
index 0000000..ca41a4f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BootStrap.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1.class
new file mode 100644
index 0000000..8af4045
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure2.class
new file mode 100644
index 0000000..7d3f214
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure3.class
new file mode 100644
index 0000000..fa2828f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure4.class
new file mode 100644
index 0000000..8c71734
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure5.class
new file mode 100644
index 0000000..88c1006
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig$_run_closure1_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig.class
new file mode 100644
index 0000000..b6d906d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/BuildConfig.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1.class
new file mode 100644
index 0000000..37f8391
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1_closure3.class
new file mode 100644
index 0000000..918be82
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1_closure4.class
new file mode 100644
index 0000000..8b41ccf
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure1_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure2.class
new file mode 100644
index 0000000..0f81823
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config$_run_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config.class
new file mode 100644
index 0000000..8d6a0a5
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/Config.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure1.class
new file mode 100644
index 0000000..178ae82
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure2.class
new file mode 100644
index 0000000..c13610b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3.class
new file mode 100644
index 0000000..f9bfa63
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure4.class
new file mode 100644
index 0000000..c4a26f6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure4_closure7.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure4_closure7.class
new file mode 100644
index 0000000..cdf042e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure4_closure7.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure5.class
new file mode 100644
index 0000000..0cac5e7
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure5_closure8.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure5_closure8.class
new file mode 100644
index 0000000..7d63db4
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure5_closure8.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6.class
new file mode 100644
index 0000000..1175bf4
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6_closure9.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6_closure9.class
new file mode 100644
index 0000000..373c8c3
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6_closure9.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6_closure9_closure10.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6_closure9_closure10.class
new file mode 100644
index 0000000..15cec06
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource$_run_closure3_closure6_closure9_closure10.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource.class
new file mode 100644
index 0000000..19ceadd
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DataSource.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DbdocUrlMappings$__clinit__closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DbdocUrlMappings$__clinit__closure1.class
new file mode 100644
index 0000000..c71b228
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DbdocUrlMappings$__clinit__closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DbdocUrlMappings.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DbdocUrlMappings.class
new file mode 100644
index 0000000..7a5098b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DbdocUrlMappings.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1.class
new file mode 100644
index 0000000..ce4daeb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1_closure2.class
new file mode 100644
index 0000000..e13b716
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1_closure3.class
new file mode 100644
index 0000000..1cbce9f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig$_run_closure1_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig.class
new file mode 100644
index 0000000..8f3b806
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultCacheConfig.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultSecurityConfig$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultSecurityConfig$_run_closure1.class
new file mode 100644
index 0000000..5b6183b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultSecurityConfig$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultSecurityConfig.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultSecurityConfig.class
new file mode 100644
index 0000000..28e13ef
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/DefaultSecurityConfig.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryConfig$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryConfig$_run_closure1.class
new file mode 100644
index 0000000..934db4a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryConfig$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryConfig.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryConfig.class
new file mode 100644
index 0000000..aaa3e3e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryConfig.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1.class
new file mode 100644
index 0000000..bf41bbb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1_closure2.class
new file mode 100644
index 0000000..ee00dda
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1_closure3.class
new file mode 100644
index 0000000..ef08c2d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources$_run_closure1_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources.class
new file mode 100644
index 0000000..981ecd8
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryPluginResources.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure1.class
new file mode 100644
index 0000000..67bf00d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2.class
new file mode 100644
index 0000000..556a82d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure4.class
new file mode 100644
index 0000000..6fa5ad2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure5.class
new file mode 100644
index 0000000..6f0dd29
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure6.class
new file mode 100644
index 0000000..e111b46
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure7.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure7.class
new file mode 100644
index 0000000..96583cc
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure2_closure7.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure3.class
new file mode 100644
index 0000000..a6d580d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib.class
new file mode 100644
index 0000000..046aecf
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryResourceTagLib.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure1.class
new file mode 100644
index 0000000..7efbb2e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure2.class
new file mode 100644
index 0000000..58207ca
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure3.class
new file mode 100644
index 0000000..768c298
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure4.class
new file mode 100644
index 0000000..e39adca
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService.class
new file mode 100644
index 0000000..12e5acb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryService.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure1.class
new file mode 100644
index 0000000..ca5192b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure1_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure1_closure6.class
new file mode 100644
index 0000000..1aed11e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure1_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure2.class
new file mode 100644
index 0000000..f325123
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure3.class
new file mode 100644
index 0000000..f70151b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure4.class
new file mode 100644
index 0000000..e1e5990
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure5.class
new file mode 100644
index 0000000..2eb1472
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib$_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib.class
new file mode 100644
index 0000000..193c302
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/JQueryTagLib.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure1.class
new file mode 100644
index 0000000..98f2a7d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure2.class
new file mode 100644
index 0000000..1a44059
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure3.class
new file mode 100644
index 0000000..cadfdc8
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure4.class
new file mode 100644
index 0000000..b4390a2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure5.class
new file mode 100644
index 0000000..967fbbd
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure6.class
new file mode 100644
index 0000000..4d5531d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure7.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure7.class
new file mode 100644
index 0000000..f31a779
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure7.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure8.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure8.class
new file mode 100644
index 0000000..5c62a01
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController$_closure8.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController.class
new file mode 100644
index 0000000..d438ed5
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LoginController.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LogoutController$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LogoutController$_closure1.class
new file mode 100644
index 0000000..a7cee34
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LogoutController$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LogoutController.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LogoutController.class
new file mode 100644
index 0000000..776f291
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/LogoutController.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap$_closure1.class
new file mode 100644
index 0000000..390aa1b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap$_closure2.class
new file mode 100644
index 0000000..799885a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap.class
new file mode 100644
index 0000000..61148e7
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/ResourcesBootStrap.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1.class
new file mode 100644
index 0000000..d56294c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1_closure2.class
new file mode 100644
index 0000000..698c0e1
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1_closure2_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1_closure2_closure3.class
new file mode 100644
index 0000000..7790789
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings$__clinit__closure1_closure2_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings.class
new file mode 100644
index 0000000..252f32b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/UrlMappings.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_globalnav.gsp b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_globalnav.gsp
new file mode 100644
index 0000000..639dd04
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_globalnav.gsp
@@ -0,0 +1,24 @@
+
+
+
+Overview
+
+
+
+
+
+Current Tables
+
+Authors
+
+Change Logs
+
+Pending Changes
+
+Pending SQL
+
+Most Recent Changes
+
+
+
+
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_index.gsp b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_index.gsp
new file mode 100644
index 0000000..f24929a
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_index.gsp
@@ -0,0 +1,22 @@
+
+
+
+Database Documentation
+
+
+
+
+
+
+
+
+
+Frame Alert
+
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+
+Link toNon-frame version.
+
+
+
+
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_overview-summary.gsp b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_overview-summary.gsp
new file mode 100644
index 0000000..8f201a1
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_overview-summary.gsp
@@ -0,0 +1,11 @@
+
+
+ Database Documentation Overview
+
+
+
+ Database Documentation
+ This report contains documentation on the database changes made.
+ Use the navigation to the left to navigate the documentation.
+
+
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_stylesheet.gsp b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_stylesheet.gsp
new file mode 100644
index 0000000..e512032
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/dbdoc/_stylesheet.gsp
@@ -0,0 +1,60 @@
+h1 {
+}
+
+.TableHeadingColor {
+ background: #ccccff; /* Dark mauve */
+}
+.TableSubHeadingColor {
+ background: #eeeeff; /* Light mauve */
+}
+.TableRowColor {
+ background: white;
+}
+
+.NavBarCell1 {
+ background-color: #eeeeff; /* Light mauve */
+}
+.NavBarCell1Rev {
+ background-color: #00008b; /* Dark Blue */
+}
+.NavBarFont1 {
+ color: black;
+}
+.NavBarFont1Rev {
+ color: white;
+}
+
+.NavBarCell2 {
+ background-color: white;
+}
+.NavBarCell3 {
+ background-color: white;
+}
+
+body {
+ background: #fff;
+ color: #333;
+ font: 12px verdana, arial, helvetica, sans-serif;
+}
+
+a:link, a:visited, a:hover {
+ color: #666;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+td, th {
+ font: 11px verdana, arial, helvetica, sans-serif;
+ line-height: 12px;
+ padding: 5px 6px;
+ text-align: left;
+ vertical-align: top;
+}
+
+th {
+ color: #666;
+ font-size: 11px;
+ font-weight: bold;
+ line-height: 17px;
+ padding: 2px 6px;
+}
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/SecuredController.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/SecuredController.class
new file mode 100644
index 0000000..8795c3f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/SecuredController.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/SecuredControllerTests.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/SecuredControllerTests.class
new file mode 100644
index 0000000..2794f03
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/SecuredControllerTests.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/UnsecuredController.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/UnsecuredController.class
new file mode 100644
index 0000000..65b33c5
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/UnsecuredController.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/UnsecuredControllerTests.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/UnsecuredControllerTests.class
new file mode 100644
index 0000000..90de5ab
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/grails/UnsecuredControllerTests.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role$__clinit__closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role$__clinit__closure1.class
new file mode 100644
index 0000000..286a81a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role$__clinit__closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role$__clinit__closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role$__clinit__closure2.class
new file mode 100644
index 0000000..a60fc95
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role$__clinit__closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role.class
new file mode 100644
index 0000000..46061ca
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/Role.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$__clinit__closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$__clinit__closure2.class
new file mode 100644
index 0000000..0a445e5
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$__clinit__closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$__clinit__closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$__clinit__closure3.class
new file mode 100644
index 0000000..510d53b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$__clinit__closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$_getAuthorities_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$_getAuthorities_closure1.class
new file mode 100644
index 0000000..7365690
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User$_getAuthorities_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User.class
new file mode 100644
index 0000000..184afa7
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/User.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/UserRole$__clinit__closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/UserRole$__clinit__closure1.class
new file mode 100644
index 0000000..fbd826f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/UserRole$__clinit__closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/UserRole.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/UserRole.class
new file mode 100644
index 0000000..70bce43
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/demo/security/UserRole.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/BlockingCache.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/BlockingCache.class
new file mode 100644
index 0000000..57cd2c1
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/BlockingCache.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheBeanPostProcessor.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheBeanPostProcessor.class
new file mode 100644
index 0000000..36aeed1
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheBeanPostProcessor.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler$CacheConfigGrailsClass.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler$CacheConfigGrailsClass.class
new file mode 100644
index 0000000..1298b97
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler$CacheConfigGrailsClass.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler$DefaultCacheConfigGrailsClass.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler$DefaultCacheConfigGrailsClass.class
new file mode 100644
index 0000000..2991b4c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler$DefaultCacheConfigGrailsClass.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler.class
new file mode 100644
index 0000000..224f752
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfigArtefactHandler.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfiguration.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfiguration.class
new file mode 100644
index 0000000..9696d9c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheConfiguration.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheEvict.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheEvict.class
new file mode 100644
index 0000000..abdbb9c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheEvict.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CachePut.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CachePut.class
new file mode 100644
index 0000000..725825e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CachePut.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib$_closure1.class
new file mode 100644
index 0000000..3d812e4
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib$_closure2.class
new file mode 100644
index 0000000..ff1922c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib.class
new file mode 100644
index 0000000..a2e2445
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/CacheTagLib.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/Cacheable.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/Cacheable.class
new file mode 100644
index 0000000..a0b73b5
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/Cacheable.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigBuilder.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigBuilder.class
new file mode 100644
index 0000000..58b7204
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigBuilder.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigLoader$_sortConfigs_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigLoader$_sortConfigs_closure1.class
new file mode 100644
index 0000000..d5ca968
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigLoader$_sortConfigs_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigLoader.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigLoader.class
new file mode 100644
index 0000000..5ac4cef
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/ConfigLoader.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource$DefaultCacheKey.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource$DefaultCacheKey.class
new file mode 100644
index 0000000..f2c3107
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource$DefaultCacheKey.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource.class
new file mode 100644
index 0000000..97a0065
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsAnnotationCacheOperationSource.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCache.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCache.class
new file mode 100644
index 0000000..3b2e5b2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCache.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCacheAdminService.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCacheAdminService.class
new file mode 100644
index 0000000..51cb079
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCacheAdminService.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCacheManager.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCacheManager.class
new file mode 100644
index 0000000..8de4d3c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsCacheManager.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsConcurrentMapCache.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsConcurrentMapCache.class
new file mode 100644
index 0000000..6bb1c1b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsConcurrentMapCache.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsConcurrentMapCacheManager.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsConcurrentMapCacheManager.class
new file mode 100644
index 0000000..289dd53
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsConcurrentMapCacheManager.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsValueWrapper.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsValueWrapper.class
new file mode 100644
index 0000000..09b5d04
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/GrailsValueWrapper.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/SerializableByteArrayOutputStream.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/SerializableByteArrayOutputStream.class
new file mode 100644
index 0000000..cc6d65f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/SerializableByteArrayOutputStream.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/SerializableOutputStream.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/SerializableOutputStream.class
new file mode 100644
index 0000000..7d06eff
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/SerializableOutputStream.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/Timer.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/Timer.class
new file mode 100644
index 0000000..3a3483b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/Timer.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/compiler/CacheTransformation.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/compiler/CacheTransformation.class
new file mode 100644
index 0000000..fd4e4d8
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/compiler/CacheTransformation.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/util/ClassUtils.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/util/ClassUtils.class
new file mode 100644
index 0000000..ed927fe
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/util/ClassUtils.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/AlreadyGzippedException.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/AlreadyGzippedException.class
new file mode 100644
index 0000000..59cc420
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/AlreadyGzippedException.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/ContentCacheParameters.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/ContentCacheParameters.class
new file mode 100644
index 0000000..a8be1f9
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/ContentCacheParameters.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/GenericResponseWrapper.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/GenericResponseWrapper.class
new file mode 100644
index 0000000..02ecd01
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/GenericResponseWrapper.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/Header$Type.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/Header$Type.class
new file mode 100644
index 0000000..0fdfb62
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/Header$Type.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/Header.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/Header.class
new file mode 100644
index 0000000..b61574b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/Header.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/HttpDateFormatter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/HttpDateFormatter.class
new file mode 100644
index 0000000..55ca636
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/HttpDateFormatter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/PageInfo.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/PageInfo.class
new file mode 100644
index 0000000..5df6cef
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/PageInfo.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/ProxyAwareMixedGrailsControllerHelper.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/ProxyAwareMixedGrailsControllerHelper.class
new file mode 100644
index 0000000..f8718ef
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/ProxyAwareMixedGrailsControllerHelper.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/SerializableCookie.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/SerializableCookie.class
new file mode 100644
index 0000000..62069b1
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/SerializableCookie.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/AbstractFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/AbstractFilter.class
new file mode 100644
index 0000000..45e7702
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/AbstractFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/CacheExpressionRootObject.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/CacheExpressionRootObject.class
new file mode 100644
index 0000000..d0bef7b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/CacheExpressionRootObject.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/CacheOperationContext.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/CacheOperationContext.class
new file mode 100644
index 0000000..2c55e50
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/CacheOperationContext.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/DefaultWebKeyGenerator.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/DefaultWebKeyGenerator.class
new file mode 100644
index 0000000..dbb6f87
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/DefaultWebKeyGenerator.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/ExpressionEvaluator.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/ExpressionEvaluator.class
new file mode 100644
index 0000000..6778ae0
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/ExpressionEvaluator.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/FilterServletOutputStream.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/FilterServletOutputStream.class
new file mode 100644
index 0000000..4d2f384
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/FilterServletOutputStream.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/LazyParamAwareEvaluationContext.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/LazyParamAwareEvaluationContext.class
new file mode 100644
index 0000000..a5c5dd4
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/LazyParamAwareEvaluationContext.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/NoOpFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/NoOpFilter.class
new file mode 100644
index 0000000..b0d5ce9
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/NoOpFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$1.class
new file mode 100644
index 0000000..5561dc2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$CacheStatus.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$CacheStatus.class
new file mode 100644
index 0000000..87f4e17
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter$CacheStatus.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter.class
new file mode 100644
index 0000000..711d0eb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/PageFragmentCachingFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/WebKeyGenerator.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/WebKeyGenerator.class
new file mode 100644
index 0000000..2defc5b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/WebKeyGenerator.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryBlockingCache.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryBlockingCache.class
new file mode 100644
index 0000000..075c3b9
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryBlockingCache.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryCacheConfiguration.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryCacheConfiguration.class
new file mode 100644
index 0000000..e05f7c0
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryCacheConfiguration.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryPageFragmentCachingFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryPageFragmentCachingFilter.class
new file mode 100644
index 0000000..1f87ac6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/cache/web/filter/simple/MemoryPageFragmentCachingFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendAttrs_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendAttrs_closure1.class
new file mode 100644
index 0000000..2f69788
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendAttrs_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendWithIndent_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendWithIndent_closure2.class
new file mode 100644
index 0000000..3906b50
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy$_appendWithIndent_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy.class
new file mode 100644
index 0000000..0d2e351
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/ChangelogXml2Groovy.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/MigrationRunner$_autoRun_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/MigrationRunner$_autoRun_closure1.class
new file mode 100644
index 0000000..1b7a8af
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/MigrationRunner$_autoRun_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/MigrationRunner.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/MigrationRunner.class
new file mode 100644
index 0000000..1196937
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/MigrationRunner.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/AuthorListWriter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/AuthorListWriter.class
new file mode 100644
index 0000000..29b45b9
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/AuthorListWriter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/ChangeLogListWriter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/ChangeLogListWriter.class
new file mode 100644
index 0000000..5422346
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/ChangeLogListWriter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/HTMLListWriter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/HTMLListWriter.class
new file mode 100644
index 0000000..6da2566
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/HTMLListWriter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/TableListWriter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/TableListWriter.class
new file mode 100644
index 0000000..494d084
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugin/databasemigration/dbdoc/TableListWriter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/BCryptPasswordEncoder.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/BCryptPasswordEncoder.class
new file mode 100644
index 0000000..e4a3f2d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/BCryptPasswordEncoder.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/DigestAuthPasswordEncoder.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/DigestAuthPasswordEncoder.class
new file mode 100644
index 0000000..c6e502b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/DigestAuthPasswordEncoder.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/Secured.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/Secured.class
new file mode 100644
index 0000000..cb5abdb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/Secured.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityConfigType.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityConfigType.class
new file mode 100644
index 0000000..8a6ba81
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityConfigType.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$__clinit__closure13.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$__clinit__closure13.class
new file mode 100644
index 0000000..0e79241
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$__clinit__closure13.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure1.class
new file mode 100644
index 0000000..7e38d07
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure10.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure10.class
new file mode 100644
index 0000000..5fc755b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure10.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure11.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure11.class
new file mode 100644
index 0000000..e64a8cc
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure11.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure12.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure12.class
new file mode 100644
index 0000000..ce5330a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure12.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure2.class
new file mode 100644
index 0000000..b65a282
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure3.class
new file mode 100644
index 0000000..f8e740c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure4.class
new file mode 100644
index 0000000..e876359
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure5.class
new file mode 100644
index 0000000..69a0bfb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure6.class
new file mode 100644
index 0000000..694c70c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure7.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure7.class
new file mode 100644
index 0000000..563350f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure7.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure8.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure8.class
new file mode 100644
index 0000000..2a10622
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure8.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure9.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure9.class
new file mode 100644
index 0000000..b64cfe2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib$_closure9.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib.class
new file mode 100644
index 0000000..edea32e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SecurityTagLib.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SpringSecurityService$_deleteRole_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SpringSecurityService$_deleteRole_closure1.class
new file mode 100644
index 0000000..6c8d7c4
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SpringSecurityService$_deleteRole_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SpringSecurityService.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SpringSecurityService.class
new file mode 100644
index 0000000..dd4749a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/grails/plugins/springsecurity/SpringSecurityService.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/messages.properties b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/messages.properties
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure1.class
new file mode 100644
index 0000000..71186e6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure2.class
new file mode 100644
index 0000000..7ec2658
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig$_init_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig.class
new file mode 100644
index 0000000..18b0679
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryConfig.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure1.class
new file mode 100644
index 0000000..1533d8f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure2.class
new file mode 100644
index 0000000..05ee858
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure3.class
new file mode 100644
index 0000000..2a46a00
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure4.class
new file mode 100644
index 0000000..3dc9b3a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider$_doRemoteFunction_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider.class
new file mode 100644
index 0000000..86e3087
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/jquery/JQueryProvider.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AbstractFilterInvocationDefinition.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AbstractFilterInvocationDefinition.class
new file mode 100644
index 0000000..ca757ee
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AbstractFilterInvocationDefinition.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAccessDeniedHandler.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAccessDeniedHandler.class
new file mode 100644
index 0000000..4d217fe
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAccessDeniedHandler.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationEntryPoint.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationEntryPoint.class
new file mode 100644
index 0000000..cd9bd92
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationEntryPoint.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationFailureHandler.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationFailureHandler.class
new file mode 100644
index 0000000..84a57f2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationFailureHandler.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationSuccessHandler.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationSuccessHandler.class
new file mode 100644
index 0000000..90a6a94
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AjaxAwareAuthenticationSuccessHandler.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AnnotationFilterInvocationDefinition.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AnnotationFilterInvocationDefinition.class
new file mode 100644
index 0000000..8927630
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AnnotationFilterInvocationDefinition.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AuthenticatedVetoableDecisionManager.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AuthenticatedVetoableDecisionManager.class
new file mode 100644
index 0000000..3473981
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/AuthenticatedVetoableDecisionManager.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ChannelFilterInvocationSecurityMetadataSourceFactoryBean.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ChannelFilterInvocationSecurityMetadataSourceFactoryBean.class
new file mode 100644
index 0000000..83decca
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ChannelFilterInvocationSecurityMetadataSourceFactoryBean.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPostAuthenticationChecks.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPostAuthenticationChecks.class
new file mode 100644
index 0000000..24660e0
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPostAuthenticationChecks.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPreAuthenticationChecks.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPreAuthenticationChecks.class
new file mode 100644
index 0000000..43efffa
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DefaultPreAuthenticationChecks.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator$1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator$1.class
new file mode 100644
index 0000000..fa52135
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator$1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator.class
new file mode 100644
index 0000000..35a3875
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyRequestCreator.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator$1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator$1.class
new file mode 100644
index 0000000..a321bd5
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator$1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator.class
new file mode 100644
index 0000000..1a1b23a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/DummyResponseCreator.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_createNewToken_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_createNewToken_closure1.class
new file mode 100644
index 0000000..1850d34
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_createNewToken_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_removeUserTokens_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_removeUserTokens_closure2.class
new file mode 100644
index 0000000..9e0f4fc
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_removeUserTokens_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_updateToken_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_updateToken_closure3.class
new file mode 100644
index 0000000..2d82658
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository$_updateToken_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository.class
new file mode 100644
index 0000000..70442ec
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormPersistentTokenRepository.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadAuthorities_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadAuthorities_closure2.class
new file mode 100644
index 0000000..e195a64
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadAuthorities_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadUserByUsername_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadUserByUsername_closure1.class
new file mode 100644
index 0000000..b9e59cf
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService$_loadUserByUsername_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService.class
new file mode 100644
index 0000000..582a757
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GormUserDetailsService.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUser.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUser.class
new file mode 100644
index 0000000..69a6c26
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUser.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUserDetailsService.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUserDetailsService.class
new file mode 100644
index 0000000..e90f8ac
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsUserDetailsService.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator$1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator$1.class
new file mode 100644
index 0000000..26d651c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator$1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator.class
new file mode 100644
index 0000000..5cb53a3
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/GrailsWebInvocationPrivilegeEvaluator.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckInsecureChannelProcessor.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckInsecureChannelProcessor.class
new file mode 100644
index 0000000..a68677e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckInsecureChannelProcessor.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckSecureChannelProcessor.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckSecureChannelProcessor.class
new file mode 100644
index 0000000..0dafb9c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/HeaderCheckSecureChannelProcessor.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/InterceptUrlMapFilterInvocationDefinition.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/InterceptUrlMapFilterInvocationDefinition.class
new file mode 100644
index 0000000..e8e8eef
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/InterceptUrlMapFilterInvocationDefinition.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/IpAddressFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/IpAddressFilter.class
new file mode 100644
index 0000000..6b55794
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/IpAddressFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter$DummyLogoutHandler.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter$DummyLogoutHandler.class
new file mode 100644
index 0000000..2442281
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter$DummyLogoutHandler.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter.class
new file mode 100644
index 0000000..01efc04
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/MutableLogoutFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullAuthenticationEventPublisher.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullAuthenticationEventPublisher.class
new file mode 100644
index 0000000..78e09ea
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullAuthenticationEventPublisher.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullLogoutHandlerRememberMeServices.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullLogoutHandlerRememberMeServices.class
new file mode 100644
index 0000000..ee0df90
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullLogoutHandlerRememberMeServices.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullSaltSource.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullSaltSource.class
new file mode 100644
index 0000000..1274423
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/NullSaltSource.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils$_splitMap_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils$_splitMap_closure1.class
new file mode 100644
index 0000000..fb80777
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils$_splitMap_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils.class
new file mode 100644
index 0000000..7c16281
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/ReflectionUtils.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestHolderAuthenticationFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestHolderAuthenticationFilter.class
new file mode 100644
index 0000000..e57d267
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestHolderAuthenticationFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestmapFilterInvocationDefinition.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestmapFilterInvocationDefinition.class
new file mode 100644
index 0000000..10e4518
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/RequestmapFilterInvocationDefinition.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityEventListener.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityEventListener.class
new file mode 100644
index 0000000..298ee3f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityEventListener.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityFilterPosition.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityFilterPosition.class
new file mode 100644
index 0000000..48c2a77
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityFilterPosition.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityRequestHolder.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityRequestHolder.class
new file mode 100644
index 0000000..a0ed74d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SecurityRequestHolder.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils$1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils$1.class
new file mode 100644
index 0000000..1ec0ecb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils$1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils.class
new file mode 100644
index 0000000..cb82c3e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionConfigAttribute.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionConfigAttribute.class
new file mode 100644
index 0000000..9d078d6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionConfigAttribute.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionVoter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionVoter.class
new file mode 100644
index 0000000..1d0bb19
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/codehaus/groovy/grails/plugins/springsecurity/WebExpressionVoter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3.class
new file mode 100644
index 0000000..abeca0f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3_closure4.class
new file mode 100644
index 0000000..7fce905
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_buildAggregateResource_closure3_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_containsResource_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_containsResource_closure1.class
new file mode 100644
index 0000000..349ae1a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_containsResource_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_isDirty_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_isDirty_closure2.class
new file mode 100644
index 0000000..72ed819
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta$_isDirty_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta.class
new file mode 100644
index 0000000..d1f75fc
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/AggregatedResourceMeta.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/BundleResourceMapper.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/BundleResourceMapper.class
new file mode 100644
index 0000000..88b884e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/BundleResourceMapper.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSBundleResourceMeta.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSBundleResourceMeta.class
new file mode 100644
index 0000000..ccdf163
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSBundleResourceMeta.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSLinkProcessor$_process_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSLinkProcessor$_process_closure1.class
new file mode 100644
index 0000000..4a647f9
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSLinkProcessor$_process_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSLinkProcessor.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSLinkProcessor.class
new file mode 100644
index 0000000..90085cc
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSLinkProcessor.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper$_map_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper$_map_closure1.class
new file mode 100644
index 0000000..c06ce35
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper$_map_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper.class
new file mode 100644
index 0000000..7c65637
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSPreprocessorResourceMapper.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1.class
new file mode 100644
index 0000000..24f3fc2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1_closure2.class
new file mode 100644
index 0000000..8c5c459
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper$_map_closure1_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper.class
new file mode 100644
index 0000000..e7a971f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/CSSRewriterResourceMapper.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/DevModeSanityFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/DevModeSanityFilter.class
new file mode 100644
index 0000000..6b52ea0
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/DevModeSanityFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/JavaScriptBundleResourceMeta.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/JavaScriptBundleResourceMeta.class
new file mode 100644
index 0000000..2f6b46f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/JavaScriptBundleResourceMeta.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ProcessingFilter.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ProcessingFilter.class
new file mode 100644
index 0000000..2ccfd63
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ProcessingFilter.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceMeta$_reset_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceMeta$_reset_closure1.class
new file mode 100644
index 0000000..f7cc850
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceMeta$_reset_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceMeta.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceMeta.class
new file mode 100644
index 0000000..18ea8b8
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceMeta.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_closure1.class
new file mode 100644
index 0000000..9910dcf
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_getRequiredDispositions_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_getRequiredDispositions_closure3.class
new file mode 100644
index 0000000..d695e2f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_getRequiredDispositions_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_newResourceFromArgs_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_newResourceFromArgs_closure2.class
new file mode 100644
index 0000000..0356953
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule$_newResourceFromArgs_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule.class
new file mode 100644
index 0000000..8265d97
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceModule.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure5.class
new file mode 100644
index 0000000..18ce674
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure6.class
new file mode 100644
index 0000000..dcbe611
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_afterPropertiesSet_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure7.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure7.class
new file mode 100644
index 0000000..f560728
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure7.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure8.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure8.class
new file mode 100644
index 0000000..ed0ad15
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_canProcessLegacyResource_closure8.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_defineModuleFromBuilder_closure16.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_defineModuleFromBuilder_closure16.class
new file mode 100644
index 0000000..59c2293
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_defineModuleFromBuilder_closure16.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21.class
new file mode 100644
index 0000000..428503c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure35.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure35.class
new file mode 100644
index 0000000..e704518
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure35.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure36.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure36.class
new file mode 100644
index 0000000..bfd4d9b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure21_closure36.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure22.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure22.class
new file mode 100644
index 0000000..492c46c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpResources_closure22.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20.class
new file mode 100644
index 0000000..5062403
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20_closure34.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20_closure34.class
new file mode 100644
index 0000000..53c68ea
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_dumpStats_closure20_closure34.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_findSyntheticResourceById_closure9.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_findSyntheticResourceById_closure9.class
new file mode 100644
index 0000000..226ec03
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_findSyntheticResourceById_closure9.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getConfigParamOrDefault_closure23.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getConfigParamOrDefault_closure23.class
new file mode 100644
index 0000000..0962770
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getConfigParamOrDefault_closure23.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10.class
new file mode 100644
index 0000000..af7b173
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10_closure27.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10_closure27.class
new file mode 100644
index 0000000..eeca60c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getResourceMetaForURI_closure10_closure27.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getServletContext_closure24.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getServletContext_closure24.class
new file mode 100644
index 0000000..45881f8
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_getServletContext_closure24.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure17.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure17.class
new file mode 100644
index 0000000..c101f1f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure17.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18.class
new file mode 100644
index 0000000..646d1c6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure30.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure30.class
new file mode 100644
index 0000000..3eab1b6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure30.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31.class
new file mode 100644
index 0000000..44d6236
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure32.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure32.class
new file mode 100644
index 0000000..ca76555
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure32.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure33.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure33.class
new file mode 100644
index 0000000..10b6b54
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure18_closure31_closure33.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure19.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure19.class
new file mode 100644
index 0000000..c67a2d9
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_loadModules_closure19.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_makeFileSystemPathFromURI_closure11.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_makeFileSystemPathFromURI_closure11.class
new file mode 100644
index 0000000..f9e9a45
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_makeFileSystemPathFromURI_closure11.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure13.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure13.class
new file mode 100644
index 0000000..4a58911
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure13.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14.class
new file mode 100644
index 0000000..a524e65
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure28.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure28.class
new file mode 100644
index 0000000..f133c71
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure28.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure29.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure29.class
new file mode 100644
index 0000000..e7b1fd8
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure14_closure29.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure15.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure15.class
new file mode 100644
index 0000000..ede0710
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareResourceBatch_closure15.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareSingleDeclaredResource_closure12.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareSingleDeclaredResource_closure12.class
new file mode 100644
index 0000000..503318a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_prepareSingleDeclaredResource_closure12.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure1.class
new file mode 100644
index 0000000..aebb653
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure2.class
new file mode 100644
index 0000000..b161b88
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3.class
new file mode 100644
index 0000000..a8fa484
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3_closure25.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3_closure25.class
new file mode 100644
index 0000000..9afefc6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure3_closure25.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4.class
new file mode 100644
index 0000000..73be28d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4_closure26.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4_closure26.class
new file mode 100644
index 0000000..35301b2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor$_updateDependencyOrder_closure4_closure26.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor.class
new file mode 100644
index 0000000..8ac30e3
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessor.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessorBatch.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessorBatch.class
new file mode 100644
index 0000000..6e6b624
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceProcessorBatch.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure13.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure13.class
new file mode 100644
index 0000000..f608841
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure13.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure14.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure14.class
new file mode 100644
index 0000000..2f9683d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$__clinit__closure14.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure1.class
new file mode 100644
index 0000000..d4a8dce
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure10.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure10.class
new file mode 100644
index 0000000..160f343
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure10.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure10_closure17.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure10_closure17.class
new file mode 100644
index 0000000..962724b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure10_closure17.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure1_closure15.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure1_closure15.class
new file mode 100644
index 0000000..5e28fba
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure1_closure15.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure2.class
new file mode 100644
index 0000000..8f6eaec
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure3.class
new file mode 100644
index 0000000..0164c9d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure4.class
new file mode 100644
index 0000000..250e081
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure5.class
new file mode 100644
index 0000000..305243a
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure5_closure16.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure5_closure16.class
new file mode 100644
index 0000000..dbef601
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure5_closure16.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure6.class
new file mode 100644
index 0000000..5bff82b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure7.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure7.class
new file mode 100644
index 0000000..0b81156
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure7.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure8.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure8.class
new file mode 100644
index 0000000..9950c34
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure8.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure9.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure9.class
new file mode 100644
index 0000000..f93febd
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_closure9.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_resolveResourceAndURI_closure12.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_resolveResourceAndURI_closure12.class
new file mode 100644
index 0000000..fe5ff3b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_resolveResourceAndURI_closure12.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_writeAttrs_closure11.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_writeAttrs_closure11.class
new file mode 100644
index 0000000..4060472
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib$_writeAttrs_closure11.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib.class
new file mode 100644
index 0000000..d5330bc
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/ResourceTagLib.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/URLUtils.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/URLUtils.class
new file mode 100644
index 0000000..2d66530
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/URLUtils.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/MapperPhase.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/MapperPhase.class
new file mode 100644
index 0000000..8e97f72
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/MapperPhase.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_closure1.class
new file mode 100644
index 0000000..1371db6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultExcludes_closure8.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultExcludes_closure8.class
new file mode 100644
index 0000000..6bed3c5
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultExcludes_closure8.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultIncludes_closure9.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultIncludes_closure9.class
new file mode 100644
index 0000000..277a047
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getDefaultIncludes_closure9.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludes_closure10.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludes_closure10.class
new file mode 100644
index 0000000..68bee10
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludes_closure10.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludingPattern_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludingPattern_closure2.class
new file mode 100644
index 0000000..ba26e31
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getExcludingPattern_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludes_closure11.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludes_closure11.class
new file mode 100644
index 0000000..c3b109b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludes_closure11.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludingPattern_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludingPattern_closure3.class
new file mode 100644
index 0000000..fea29ac
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getIncludingPattern_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getName_closure7.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getName_closure7.class
new file mode 100644
index 0000000..a046e54
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getName_closure7.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getOperation_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getOperation_closure5.class
new file mode 100644
index 0000000..4c37e76
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getOperation_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPhase_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPhase_closure4.class
new file mode 100644
index 0000000..83511ea
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPhase_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPriority_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPriority_closure6.class
new file mode 100644
index 0000000..2f2d6e0
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper$_getPriority_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper.class
new file mode 100644
index 0000000..52b220d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMapper.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure1.class
new file mode 100644
index 0000000..67a8d35
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2.class
new file mode 100644
index 0000000..5e6a2b7
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2_closure7.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2_closure7.class
new file mode 100644
index 0000000..bd6b6c7
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure2_closure7.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure3.class
new file mode 100644
index 0000000..1737be7
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure4.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure4.class
new file mode 100644
index 0000000..0ee6266
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure4.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure5.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure5.class
new file mode 100644
index 0000000..f573017
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure5.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure6.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure6.class
new file mode 100644
index 0000000..a2eb189
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory$_createResourceMappers_closure6.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory.class
new file mode 100644
index 0000000..a970bb9
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/mapper/ResourceMappersFactory.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleBuilder.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleBuilder.class
new file mode 100644
index 0000000..8bd78cb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleBuilder.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure1.class
new file mode 100644
index 0000000..9efc233
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure2.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure2.class
new file mode 100644
index 0000000..28844d8
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure2.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure3.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure3.class
new file mode 100644
index 0000000..f8b9ac2
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory$_getModuleDeclarations_closure3.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory.class
new file mode 100644
index 0000000..a1adf63
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModuleDeclarationsFactory.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModulesBuilder$_invokeMethod_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModulesBuilder$_invokeMethod_closure1.class
new file mode 100644
index 0000000..c073429
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModulesBuilder$_invokeMethod_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModulesBuilder.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModulesBuilder.class
new file mode 100644
index 0000000..715bd37
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/module/ModulesBuilder.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/HalfBakedLegacyLinkGenerator.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/HalfBakedLegacyLinkGenerator.class
new file mode 100644
index 0000000..9abca2b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/HalfBakedLegacyLinkGenerator.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/ResourceMetaStore$_addResource_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/ResourceMetaStore$_addResource_closure1.class
new file mode 100644
index 0000000..9b9bcee
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/ResourceMetaStore$_addResource_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/ResourceMetaStore.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/ResourceMetaStore.class
new file mode 100644
index 0000000..8fad0c7
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resource/util/ResourceMetaStore.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/AbstractResourcesArtefactHandler.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/AbstractResourcesArtefactHandler.class
new file mode 100644
index 0000000..77451f6
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/AbstractResourcesArtefactHandler.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/DefaultResourceMapperClass.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/DefaultResourceMapperClass.class
new file mode 100644
index 0000000..6b6a140
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/DefaultResourceMapperClass.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/DefaultResourcesClass.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/DefaultResourcesClass.class
new file mode 100644
index 0000000..9720ee0
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/DefaultResourcesClass.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourceMapperArtefactHandler.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourceMapperArtefactHandler.class
new file mode 100644
index 0000000..d8e2add
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourceMapperArtefactHandler.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourceMapperClass.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourceMapperClass.class
new file mode 100644
index 0000000..4c6e3a1
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourceMapperClass.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourcesArtefactHandler.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourcesArtefactHandler.class
new file mode 100644
index 0000000..5f3562b
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourcesArtefactHandler.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourcesClass.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourcesClass.class
new file mode 100644
index 0000000..5a344ff
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/grails/plugin/resources/artefacts/ResourcesClass.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/mindrot/jbcrypt/BCrypt.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/mindrot/jbcrypt/BCrypt.class
new file mode 100644
index 0000000..cf0e1b5
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/org/mindrot/jbcrypt/BCrypt.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/resources$_run_closure1.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/resources$_run_closure1.class
new file mode 100644
index 0000000..62321cd
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/resources$_run_closure1.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/resources.class b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/resources.class
new file mode 100644
index 0000000..b7b8fe8
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/resources.class differ
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core.properties b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core.properties
new file mode 100644
index 0000000..13fdc56
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core.properties
@@ -0,0 +1,18 @@
+# Login errors
+springSecurity.errors.login.expired=Sorry, your account has expired.
+springSecurity.errors.login.passwordExpired=Sorry, your password has expired.
+springSecurity.errors.login.disabled=Sorry, your account is disabled.
+springSecurity.errors.login.locked=Sorry, your account is locked.
+springSecurity.errors.login.fail=Sorry, we were not able to find a user with that username and password.
+
+# Login Page
+springSecurity.login.title=Login
+springSecurity.login.header=Please Login
+springSecurity.login.button=Login
+springSecurity.login.username.label=Username
+springSecurity.login.password.label=Password
+springSecurity.login.remember.me.label=Remember me
+
+# Denied Page
+springSecurity.denied.title=Denied
+springSecurity.denied.message=Sorry, you're not authorized to view this page.
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core_de.properties b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core_de.properties
new file mode 100644
index 0000000..b237c43
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core_de.properties
@@ -0,0 +1,18 @@
+# Login errors
+springSecurity.errors.login.expired=Die Gltigkeit ihres Zugangs ist leider abgelaufen.
+springSecurity.errors.login.passwordExpire=Die Gltigkeit ihres Passwortes ist leider abgelaufen.
+springSecurity.errors.login.disabled=Ihr Zugang wurde leider deaktiviert.
+springSecurity.errors.login.locked=Ihr Zugang wurde leider gesperrt.
+springSecurity.errors.login.fail=Es konnte leider kein Zugang mit dem entsprechenden Benutzernamen und Passwort gefunden werden.
+
+# Login Page
+springSecurity.login.title=Anmeldung
+springSecurity.login.header=Bitte anmelden
+springSecurity.login.button=Anmelden
+springSecurity.login.username.label=Benutzername
+springSecurity.login.password.label=Passwort
+springSecurity.login.remember.me.label=Angemeldet bleiben
+
+# Denied Page
+springSecurity.denied.title=Zugriff abgelehnt
+springSecurity.denied.message=Sie sind leider nicht dazu berechtigt, diese Seite zu betrachten.
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core_fr.properties b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core_fr.properties
new file mode 100644
index 0000000..b2d37d4
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/classes/spring-security-core_fr.properties
@@ -0,0 +1,18 @@
+# Login errors
+springSecurity.errors.login.expired=Dsol, votre compte a expir.
+springSecurity.errors.login.passwordExpired=Dsol, votre mot de passe a expir.
+springSecurity.errors.login.disabled=Dsol, votre compte est dsactiv.
+springSecurity.errors.login.locked=Dsol, votre compte est vrouill.
+springSecurity.errors.login.fail=Dsol, nous n'avons pas pu trouver d'utilisateur avec ce login et ce mot de passe.
+
+# Login Page
+springSecurity.login.title=Login
+springSecurity.login.header=Connectez-vous l'aide de vos identifiants
+springSecurity.login.button=Connexion
+springSecurity.login.username.label=Nom d'utilisateur
+springSecurity.login.password.label=Mot de passe
+springSecurity.login.remember.me.label=Rester connect
+
+# Denied Page
+springSecurity.denied.title=Accs refus
+springSecurity.denied.message=Dsol, vous n'tes pas autoriss accder cette page.
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/sitemesh.xml b/ch09/ch10/demo-grails/web-app/WEB-INF/sitemesh.xml
new file mode 100644
index 0000000..72399ce
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/sitemesh.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/tld/c.tld b/ch09/ch10/demo-grails/web-app/WEB-INF/tld/c.tld
new file mode 100644
index 0000000..5e18236
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/tld/c.tld
@@ -0,0 +1,572 @@
+
+
+
+
+ JSTL 1.2 core library
+ JSTL core
+ 1.2
+ c
+ http://java.sun.com/jsp/jstl/core
+
+
+
+ Provides core validation features for JSTL tags.
+
+
+ org.apache.taglibs.standard.tlv.JstlCoreTLV
+
+
+
+
+
+ Catches any Throwable that occurs in its body and optionally
+ exposes it.
+
+ catch
+ org.apache.taglibs.standard.tag.common.core.CatchTag
+ JSP
+
+
+Name of the exported scoped variable for the
+exception thrown from a nested action. The type of the
+scoped variable is the type of the exception thrown.
+
+ var
+ false
+ false
+
+
+
+
+
+ Simple conditional tag that establishes a context for
+ mutually exclusive conditional operations, marked by
+ <when> and <otherwise>
+
+ choose
+ org.apache.taglibs.standard.tag.common.core.ChooseTag
+ JSP
+
+
+
+
+ Simple conditional tag, which evalutes its body if the
+ supplied condition is true and optionally exposes a Boolean
+ scripting variable representing the evaluation of this condition
+
+ if
+ org.apache.taglibs.standard.tag.rt.core.IfTag
+ JSP
+
+
+The test condition that determines whether or
+not the body content should be processed.
+
+ test
+ true
+ true
+ boolean
+
+
+
+Name of the exported scoped variable for the
+resulting value of the test condition. The type
+of the scoped variable is Boolean.
+
+ var
+ false
+ false
+
+
+
+Scope for var.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Retrieves an absolute or relative URL and exposes its contents
+ to either the page, a String in 'var', or a Reader in 'varReader'.
+
+ import
+ org.apache.taglibs.standard.tag.rt.core.ImportTag
+ org.apache.taglibs.standard.tei.ImportTEI
+ JSP
+
+
+The URL of the resource to import.
+
+ url
+ true
+ true
+
+
+
+Name of the exported scoped variable for the
+resource's content. The type of the scoped
+variable is String.
+
+ var
+ false
+ false
+
+
+
+Scope for var.
+
+ scope
+ false
+ false
+
+
+
+Name of the exported scoped variable for the
+resource's content. The type of the scoped
+variable is Reader.
+
+ varReader
+ false
+ false
+
+
+
+Name of the context when accessing a relative
+URL resource that belongs to a foreign
+context.
+
+ context
+ false
+ true
+
+
+
+Character encoding of the content at the input
+resource.
+
+ charEncoding
+ false
+ true
+
+
+
+
+
+ The basic iteration tag, accepting many different
+ collection types and supporting subsetting and other
+ functionality
+
+ forEach
+ org.apache.taglibs.standard.tag.rt.core.ForEachTag
+ org.apache.taglibs.standard.tei.ForEachTEI
+ JSP
+
+
+Collection of items to iterate over.
+
+ items
+ false
+ true
+ java.lang.Object
+
+ java.lang.Object
+
+
+
+
+If items specified:
+Iteration begins at the item located at the
+specified index. First item of the collection has
+index 0.
+If items not specified:
+Iteration begins with index set at the value
+specified.
+
+ begin
+ false
+ true
+ int
+
+
+
+If items specified:
+Iteration ends at the item located at the
+specified index (inclusive).
+If items not specified:
+Iteration ends when index reaches the value
+specified.
+
+ end
+ false
+ true
+ int
+
+
+
+Iteration will only process every step items of
+the collection, starting with the first one.
+
+ step
+ false
+ true
+ int
+
+
+
+Name of the exported scoped variable for the
+current item of the iteration. This scoped
+variable has nested visibility. Its type depends
+on the object of the underlying collection.
+
+ var
+ false
+ false
+
+
+
+Name of the exported scoped variable for the
+status of the iteration. Object exported is of type
+javax.servlet.jsp.jstl.core.LoopTagStatus. This scoped variable has nested
+visibility.
+
+ varStatus
+ false
+ false
+
+
+
+
+
+ Iterates over tokens, separated by the supplied delimeters
+
+ forTokens
+ org.apache.taglibs.standard.tag.rt.core.ForTokensTag
+ JSP
+
+
+String of tokens to iterate over.
+
+ items
+ true
+ true
+ java.lang.String
+
+ java.lang.String
+
+
+
+
+The set of delimiters (the characters that
+separate the tokens in the string).
+
+ delims
+ true
+ true
+ java.lang.String
+
+
+
+Iteration begins at the token located at the
+specified index. First token has index 0.
+
+ begin
+ false
+ true
+ int
+
+
+
+Iteration ends at the token located at the
+specified index (inclusive).
+
+ end
+ false
+ true
+ int
+
+
+
+Iteration will only process every step tokens
+of the string, starting with the first one.
+
+ step
+ false
+ true
+ int
+
+
+
+Name of the exported scoped variable for the
+current item of the iteration. This scoped
+variable has nested visibility.
+
+ var
+ false
+ false
+
+
+
+Name of the exported scoped variable for the
+status of the iteration. Object exported is of
+type
+javax.servlet.jsp.jstl.core.LoopTag
+Status. This scoped variable has nested
+visibility.
+
+ varStatus
+ false
+ false
+
+
+
+
+
+ Like <%= ... >, but for expressions.
+
+ out
+ org.apache.taglibs.standard.tag.rt.core.OutTag
+ JSP
+
+
+Expression to be evaluated.
+
+ value
+ true
+ true
+
+
+
+Default value if the resulting value is null.
+
+ default
+ false
+ true
+
+
+
+Determines whether characters <,>,&,'," in the
+resulting string should be converted to their
+corresponding character entity codes. Default value is
+true.
+
+ escapeXml
+ false
+ true
+
+
+
+
+
+
+ Subtag of <choose> that follows <when> tags
+ and runs only if all of the prior conditions evaluated to
+ 'false'
+
+ otherwise
+ org.apache.taglibs.standard.tag.common.core.OtherwiseTag
+ JSP
+
+
+
+
+ Adds a parameter to a containing 'import' tag's URL.
+
+ param
+ org.apache.taglibs.standard.tag.rt.core.ParamTag
+ JSP
+
+
+Name of the query string parameter.
+
+ name
+ true
+ true
+
+
+
+Value of the parameter.
+
+ value
+ false
+ true
+
+
+
+
+
+ Redirects to a new URL.
+
+ redirect
+ org.apache.taglibs.standard.tag.rt.core.RedirectTag
+ JSP
+
+
+The URL of the resource to redirect to.
+
+ url
+ false
+ true
+
+
+
+Name of the context when redirecting to a relative URL
+resource that belongs to a foreign context.
+
+ context
+ false
+ true
+
+
+
+
+
+ Removes a scoped variable (from a particular scope, if specified).
+
+ remove
+ org.apache.taglibs.standard.tag.common.core.RemoveTag
+ empty
+
+
+Name of the scoped variable to be removed.
+
+ var
+ true
+ false
+
+
+
+Scope for var.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Sets the result of an expression evaluation in a 'scope'
+
+ set
+ org.apache.taglibs.standard.tag.rt.core.SetTag
+ JSP
+
+
+Name of the exported scoped variable to hold the value
+specified in the action. The type of the scoped variable is
+whatever type the value expression evaluates to.
+
+ var
+ false
+ false
+
+
+
+Expression to be evaluated.
+
+ value
+ false
+ true
+
+ java.lang.Object
+
+
+
+
+Target object whose property will be set. Must evaluate to
+a JavaBeans object with setter property property, or to a
+java.util.Map object.
+
+ target
+ false
+ true
+
+
+
+Name of the property to be set in the target object.
+
+ property
+ false
+ true
+
+
+
+Scope for var.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Creates a URL with optional query parameters.
+
+ url
+ org.apache.taglibs.standard.tag.rt.core.UrlTag
+ JSP
+
+
+Name of the exported scoped variable for the
+processed url. The type of the scoped variable is
+String.
+
+ var
+ false
+ false
+
+
+
+Scope for var.
+
+ scope
+ false
+ false
+
+
+
+URL to be processed.
+
+ value
+ false
+ true
+
+
+
+Name of the context when specifying a relative URL
+resource that belongs to a foreign context.
+
+ context
+ false
+ true
+
+
+
+
+
+ Subtag of <choose> that includes its body if its
+ condition evalutes to 'true'
+
+ when
+ org.apache.taglibs.standard.tag.rt.core.WhenTag
+ JSP
+
+
+The test condition that determines whether or not the
+body content should be processed.
+
+ test
+ true
+ true
+ boolean
+
+
+
+
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/tld/fmt.tld b/ch09/ch10/demo-grails/web-app/WEB-INF/tld/fmt.tld
new file mode 100644
index 0000000..2ae4776
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/tld/fmt.tld
@@ -0,0 +1,671 @@
+
+
+
+
+ JSTL 1.2 i18n-capable formatting library
+ JSTL fmt
+ 1.2
+ fmt
+ http://java.sun.com/jsp/jstl/fmt
+
+
+
+ Provides core validation features for JSTL tags.
+
+
+ org.apache.taglibs.standard.tlv.JstlFmtTLV
+
+
+
+
+
+ Sets the request character encoding
+
+ requestEncoding
+ org.apache.taglibs.standard.tag.rt.fmt.RequestEncodingTag
+ empty
+
+
+Name of character encoding to be applied when
+decoding request parameters.
+
+ value
+ false
+ true
+
+
+
+
+
+ Stores the given locale in the locale configuration variable
+
+ setLocale
+ org.apache.taglibs.standard.tag.rt.fmt.SetLocaleTag
+ empty
+
+
+A String value is interpreted as the
+printable representation of a locale, which
+must contain a two-letter (lower-case)
+language code (as defined by ISO-639),
+and may contain a two-letter (upper-case)
+country code (as defined by ISO-3166).
+Language and country codes must be
+separated by hyphen (-) or underscore
+(_).
+
+ value
+ true
+ true
+
+
+
+Vendor- or browser-specific variant.
+See the java.util.Locale javadocs for
+more information on variants.
+
+ variant
+ false
+ true
+
+
+
+Scope of the locale configuration variable.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Specifies the time zone for any time formatting or parsing actions
+ nested in its body
+
+ timeZone
+ org.apache.taglibs.standard.tag.rt.fmt.TimeZoneTag
+ JSP
+
+
+The time zone. A String value is interpreted as
+a time zone ID. This may be one of the time zone
+IDs supported by the Java platform (such as
+"America/Los_Angeles") or a custom time zone
+ID (such as "GMT-8"). See
+java.util.TimeZone for more information on
+supported time zone formats.
+
+ value
+ true
+ true
+
+
+
+
+
+ Stores the given time zone in the time zone configuration variable
+
+ setTimeZone
+ org.apache.taglibs.standard.tag.rt.fmt.SetTimeZoneTag
+ empty
+
+
+The time zone. A String value is interpreted as
+a time zone ID. This may be one of the time zone
+IDs supported by the Java platform (such as
+"America/Los_Angeles") or a custom time zone
+ID (such as "GMT-8"). See java.util.TimeZone for
+more information on supported time zone
+formats.
+
+ value
+ true
+ true
+
+
+
+Name of the exported scoped variable which
+stores the time zone of type
+java.util.TimeZone.
+
+ var
+ false
+ false
+
+
+
+Scope of var or the time zone configuration
+variable.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Loads a resource bundle to be used by its tag body
+
+ bundle
+ org.apache.taglibs.standard.tag.rt.fmt.BundleTag
+ JSP
+
+
+Resource bundle base name. This is the bundle's
+fully-qualified resource name, which has the same
+form as a fully-qualified class name, that is, it uses
+"." as the package component separator and does not
+have any file type (such as ".class" or ".properties")
+suffix.
+
+ basename
+ true
+ true
+
+
+
+Prefix to be prepended to the value of the message
+key of any nested <fmt:message> action.
+
+ prefix
+ false
+ true
+
+
+
+
+
+ Loads a resource bundle and stores it in the named scoped variable or
+ the bundle configuration variable
+
+ setBundle
+ org.apache.taglibs.standard.tag.rt.fmt.SetBundleTag
+ empty
+
+
+Resource bundle base name. This is the bundle's
+fully-qualified resource name, which has the same
+form as a fully-qualified class name, that is, it uses
+"." as the package component separator and does not
+have any file type (such as ".class" or ".properties")
+suffix.
+
+ basename
+ true
+ true
+
+
+
+Name of the exported scoped variable which stores
+the i18n localization context of type
+javax.servlet.jsp.jstl.fmt.LocalizationC
+ontext.
+
+ var
+ false
+ false
+
+
+
+Scope of var or the localization context
+configuration variable.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Maps key to localized message and performs parametric replacement
+
+ message
+ org.apache.taglibs.standard.tag.rt.fmt.MessageTag
+ JSP
+
+
+Message key to be looked up.
+
+ key
+ false
+ true
+
+
+
+Localization context in whose resource
+bundle the message key is looked up.
+
+ bundle
+ false
+ true
+
+
+
+Name of the exported scoped variable
+which stores the localized message.
+
+ var
+ false
+ false
+
+
+
+Scope of var.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Supplies an argument for parametric replacement to a containing
+ <message> tag
+
+ param
+ org.apache.taglibs.standard.tag.rt.fmt.ParamTag
+ JSP
+
+
+Argument used for parametric replacement.
+
+ value
+ false
+ true
+
+
+
+
+
+ Formats a numeric value as a number, currency, or percentage
+
+ formatNumber
+ org.apache.taglibs.standard.tag.rt.fmt.FormatNumberTag
+ JSP
+
+
+Numeric value to be formatted.
+
+ value
+ false
+ true
+
+
+
+Specifies whether the value is to be
+formatted as number, currency, or
+percentage.
+
+ type
+ false
+ true
+
+
+
+Custom formatting pattern.
+
+ pattern
+ false
+ true
+
+
+
+ISO 4217 currency code. Applied only
+when formatting currencies (i.e. if type is
+equal to "currency"); ignored otherwise.
+
+ currencyCode
+ false
+ true
+
+
+
+Currency symbol. Applied only when
+formatting currencies (i.e. if type is equal
+to "currency"); ignored otherwise.
+
+ currencySymbol
+ false
+ true
+
+
+
+Specifies whether the formatted output
+will contain any grouping separators.
+
+ groupingUsed
+ false
+ true
+
+
+
+Maximum number of digits in the integer
+portion of the formatted output.
+
+ maxIntegerDigits
+ false
+ true
+
+
+
+Minimum number of digits in the integer
+portion of the formatted output.
+
+ minIntegerDigits
+ false
+ true
+
+
+
+Maximum number of digits in the
+fractional portion of the formatted output.
+
+ maxFractionDigits
+ false
+ true
+
+
+
+Minimum number of digits in the
+fractional portion of the formatted output.
+
+ minFractionDigits
+ false
+ true
+
+
+
+Name of the exported scoped variable
+which stores the formatted result as a
+String.
+
+ var
+ false
+ false
+
+
+
+Scope of var.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Parses the string representation of a number, currency, or percentage
+
+ parseNumber
+ org.apache.taglibs.standard.tag.rt.fmt.ParseNumberTag
+ JSP
+
+
+String to be parsed.
+
+ value
+ false
+ true
+
+
+
+Specifies whether the string in the value
+attribute should be parsed as a number,
+currency, or percentage.
+
+ type
+ false
+ true
+
+
+
+Custom formatting pattern that determines
+how the string in the value attribute is to be
+parsed.
+
+ pattern
+ false
+ true
+
+
+
+Locale whose default formatting pattern (for
+numbers, currencies, or percentages,
+respectively) is to be used during the parse
+operation, or to which the pattern specified
+via the pattern attribute (if present) is
+applied.
+
+ parseLocale
+ false
+ true
+
+
+
+Specifies whether just the integer portion of
+the given value should be parsed.
+
+ integerOnly
+ false
+ true
+
+
+
+Name of the exported scoped variable which
+stores the parsed result (of type
+java.lang.Number).
+
+ var
+ false
+ false
+
+
+
+Scope of var.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Formats a date and/or time using the supplied styles and pattern
+
+ formatDate
+ org.apache.taglibs.standard.tag.rt.fmt.FormatDateTag
+ empty
+
+
+Date and/or time to be formatted.
+
+ value
+ true
+ true
+
+
+
+Specifies whether the time, the date, or both
+the time and date components of the given
+date are to be formatted.
+
+ type
+ false
+ true
+
+
+
+Predefined formatting style for dates. Follows
+the semantics defined in class
+java.text.DateFormat. Applied only
+when formatting a date or both a date and
+time (i.e. if type is missing or is equal to
+"date" or "both"); ignored otherwise.
+
+ dateStyle
+ false
+ true
+
+
+
+Predefined formatting style for times. Follows
+the semantics defined in class
+java.text.DateFormat. Applied only
+when formatting a time or both a date and
+time (i.e. if type is equal to "time" or "both");
+ignored otherwise.
+
+ timeStyle
+ false
+ true
+
+
+
+Custom formatting style for dates and times.
+
+ pattern
+ false
+ true
+
+
+
+Time zone in which to represent the formatted
+time.
+
+ timeZone
+ false
+ true
+
+
+
+Name of the exported scoped variable which
+stores the formatted result as a String.
+
+ var
+ false
+ false
+
+
+
+Scope of var.
+
+ scope
+ false
+ false
+
+
+
+
+
+ Parses the string representation of a date and/or time
+
+ parseDate
+ org.apache.taglibs.standard.tag.rt.fmt.ParseDateTag
+ JSP
+
+
+Date string to be parsed.
+
+ value
+ false
+ true
+
+
+
+Specifies whether the date string in the
+value attribute is supposed to contain a
+time, a date, or both.
+
+ type
+ false
+ true
+
+
+
+Predefined formatting style for days
+which determines how the date
+component of the date string is to be
+parsed. Applied only when formatting a
+date or both a date and time (i.e. if type
+is missing or is equal to "date" or "both");
+ignored otherwise.
+
+ dateStyle
+ false
+ true
+
+
+
+Predefined formatting styles for times
+which determines how the time
+component in the date string is to be
+parsed. Applied only when formatting a
+time or both a date and time (i.e. if type
+is equal to "time" or "both"); ignored
+otherwise.
+
+ timeStyle
+ false
+ true
+
+
+
+Custom formatting pattern which
+determines how the date string is to be
+parsed.
+
+ pattern
+ false
+ true
+
+
+
+Time zone in which to interpret any time
+information in the date string.
+
+ timeZone
+ false
+ true
+
+
+
+Locale whose predefined formatting styles
+for dates and times are to be used during
+the parse operation, or to which the
+pattern specified via the pattern
+attribute (if present) is applied.
+
+ parseLocale
+ false
+ true
+
+
+
+Name of the exported scoped variable in
+which the parsing result (of type
+java.util.Date) is stored.
+
+ var
+ false
+ false
+
+
+
+Scope of var.
+
+ scope
+ false
+ false
+
+
+
+
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/tld/grails.tld b/ch09/ch10/demo-grails/web-app/WEB-INF/tld/grails.tld
new file mode 100644
index 0000000..9bd036b
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/tld/grails.tld
@@ -0,0 +1,550 @@
+
+
+ The Grails custom tag library
+ 0.2
+ grails
+ http://grails.codehaus.org/tags
+
+
+ link
+ org.codehaus.groovy.grails.web.taglib.jsp.JspLinkTag
+ JSP
+
+ action
+ false
+ true
+
+
+ controller
+ false
+ true
+
+
+ id
+ false
+ true
+
+
+ url
+ false
+ true
+
+
+ params
+ false
+ true
+
+ true
+
+
+ form
+ org.codehaus.groovy.grails.web.taglib.jsp.JspFormTag
+ JSP
+
+ action
+ false
+ true
+
+
+ controller
+ false
+ true
+
+
+ id
+ false
+ true
+
+
+ url
+ false
+ true
+
+
+ method
+ true
+ true
+
+ true
+
+
+ select
+ org.codehaus.groovy.grails.web.taglib.jsp.JspSelectTag
+ JSP
+
+ name
+ true
+ true
+
+
+ value
+ false
+ true
+
+
+ optionKey
+ false
+ true
+
+
+ optionValue
+ false
+ true
+
+ true
+
+
+ datePicker
+ org.codehaus.groovy.grails.web.taglib.jsp.JspDatePickerTag
+ empty
+
+ name
+ true
+ true
+
+
+ value
+ false
+ true
+
+
+ precision
+ false
+ true
+
+ false
+
+
+ currencySelect
+ org.codehaus.groovy.grails.web.taglib.jsp.JspCurrencySelectTag
+ empty
+
+ name
+ true
+ true
+
+
+ value
+ false
+ true
+
+ true
+
+
+ localeSelect
+ org.codehaus.groovy.grails.web.taglib.jsp.JspLocaleSelectTag
+ empty
+
+ name
+ true
+ true
+
+
+ value
+ false
+ true
+
+ true
+
+
+ timeZoneSelect
+ org.codehaus.groovy.grails.web.taglib.jsp.JspTimeZoneSelectTag
+ empty
+
+ name
+ true
+ true
+
+
+ value
+ false
+ true
+
+ true
+
+
+ checkBox
+ org.codehaus.groovy.grails.web.taglib.jsp.JspCheckboxTag
+ empty
+
+ name
+ true
+ true
+
+
+ value
+ true
+ true
+
+ true
+
+
+ hasErrors
+ org.codehaus.groovy.grails.web.taglib.jsp.JspHasErrorsTag
+ JSP
+
+ model
+ false
+ true
+
+
+ bean
+ false
+ true
+
+
+ field
+ false
+ true
+
+ false
+
+
+ eachError
+ org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag
+ JSP
+
+ model
+ false
+ true
+
+
+ bean
+ false
+ true
+
+
+ field
+ false
+ true
+
+ false
+
+
+ renderErrors
+ org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag
+ JSP
+
+ model
+ false
+ true
+
+
+ bean
+ false
+ true
+
+
+ field
+ false
+ true
+
+
+ as
+ true
+ true
+
+ false
+
+
+ message
+ org.codehaus.groovy.grails.web.taglib.jsp.JspMessageTag
+ JSP
+
+ code
+ false
+ true
+
+
+ error
+ false
+ true
+
+
+ default
+ false
+ true
+
+ false
+
+
+ remoteFunction
+ org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteFunctionTag
+ empty
+
+ before
+ false
+ true
+
+
+ after
+ false
+ true
+
+
+ action
+ false
+ true
+
+
+ controller
+ false
+ true
+
+
+ id
+ false
+ true
+
+
+ url
+ false
+ true
+
+
+ params
+ false
+ true
+
+
+ asynchronous
+ false
+ true
+
+
+ method
+ false
+ true
+
+
+ update
+ false
+ true
+
+
+ onSuccess
+ false
+ true
+
+
+ onFailure
+ false
+ true
+
+
+ onComplete
+ false
+ true
+
+
+ onLoading
+ false
+ true
+
+
+ onLoaded
+ false
+ true
+
+
+ onInteractive
+ false
+ true
+
+ true
+
+
+ remoteLink
+ org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteLinkTag
+ JSP
+
+ before
+ false
+ true
+
+
+ after
+ false
+ true
+
+
+ action
+ false
+ true
+
+
+ controller
+ false
+ true
+
+
+ id
+ false
+ true
+
+
+ url
+ false
+ true
+
+
+ params
+ false
+ true
+
+
+ asynchronous
+ false
+ true
+
+
+ method
+ false
+ true
+
+
+ update
+ false
+ true
+
+
+ onSuccess
+ false
+ true
+
+
+ onFailure
+ false
+ true
+
+
+ onComplete
+ false
+ true
+
+
+ onLoading
+ false
+ true
+
+
+ onLoaded
+ false
+ true
+
+
+ onInteractive
+ false
+ true
+
+ true
+
+
+ formRemote
+ org.codehaus.groovy.grails.web.taglib.jsp.JspFormRemoteTag
+ JSP
+
+ before
+ false
+ true
+
+
+ after
+ false
+ true
+
+
+ action
+ false
+ true
+
+
+ controller
+ false
+ true
+
+
+ id
+ false
+ true
+
+
+ url
+ false
+ true
+
+
+ params
+ false
+ true
+
+
+ asynchronous
+ false
+ true
+
+
+ method
+ false
+ true
+
+
+ update
+ false
+ true
+
+
+ onSuccess
+ false
+ true
+
+
+ onFailure
+ false
+ true
+
+
+ onComplete
+ false
+ true
+
+
+ onLoading
+ false
+ true
+
+
+ onLoaded
+ false
+ true
+
+
+ onInteractive
+ false
+ true
+
+ true
+
+
+ invokeTag
+ org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag
+ JSP
+
+ it
+ java.lang.Object
+ true
+ NESTED
+
+
+ tagName
+ true
+ true
+
+ true
+
+
+
diff --git a/ch09/ch10/demo-grails/web-app/WEB-INF/tld/spring.tld b/ch09/ch10/demo-grails/web-app/WEB-INF/tld/spring.tld
new file mode 100644
index 0000000..1bc7091
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/WEB-INF/tld/spring.tld
@@ -0,0 +1,311 @@
+
+
+
+
+
+ 1.1.1
+
+ 1.2
+
+ Spring
+
+ http://www.springframework.org/tags
+
+ Spring Framework JSP Tag Library. Authors: Rod Johnson, Juergen Hoeller
+
+
+
+
+ htmlEscape
+ org.springframework.web.servlet.tags.HtmlEscapeTag
+ JSP
+
+
+ Sets default HTML escape value for the current page.
+ Overrides a "defaultHtmlEscape" context-param in web.xml, if any.
+
+
+
+ defaultHtmlEscape
+ true
+ true
+
+
+
+
+
+
+
+ escapeBody
+ org.springframework.web.servlet.tags.EscapeBodyTag
+ JSP
+
+
+ Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping.
+ The HTML escaping flag participates in a page-wide or application-wide setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+
+
+
+ htmlEscape
+ false
+ true
+
+
+
+ javaScriptEscape
+ false
+ true
+
+
+
+
+
+
+
+ message
+ org.springframework.web.servlet.tags.MessageTag
+ JSP
+
+
+ Retrieves the message with the given code, or text if code isn't resolvable.
+ The HTML escaping flag participates in a page-wide or application-wide setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+
+
+
+ code
+ false
+ true
+
+
+
+ arguments
+ false
+ true
+
+
+
+ text
+ false
+ true
+
+
+
+ var
+ false
+ true
+
+
+
+ scope
+ false
+ true
+
+
+
+ htmlEscape
+ false
+ true
+
+
+
+ javaScriptEscape
+ false
+ true
+
+
+
+
+
+
+
+ theme
+ org.springframework.web.servlet.tags.ThemeTag
+ JSP
+
+
+ Retrieves the theme message with the given code, or text if code isn't resolvable.
+ The HTML escaping flag participates in a page-wide or application-wide setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+
+
+
+ code
+ false
+ true
+
+
+
+ arguments
+ false
+ true
+
+
+
+ text
+ false
+ true
+
+
+
+ var
+ false
+ true
+
+
+
+ scope
+ false
+ true
+
+
+
+ htmlEscape
+ false
+ true
+
+
+
+ javaScriptEscape
+ false
+ true
+
+
+
+
+
+
+
+ hasBindErrors
+ org.springframework.web.servlet.tags.BindErrorsTag
+ JSP
+
+
+ Provides Errors instance in case of bind errors.
+ The HTML escaping flag participates in a page-wide or application-wide setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+
+
+
+ errors
+ org.springframework.validation.Errors
+
+
+
+ name
+ true
+ true
+
+
+
+ htmlEscape
+ false
+ true
+
+
+
+
+
+
+
+ nestedPath
+ org.springframework.web.servlet.tags.NestedPathTag
+ JSP
+
+
+ Sets a nested path to be used by the bind tag's path.
+
+
+
+ nestedPath
+ java.lang.String
+
+
+
+ path
+ true
+ true
+
+
+
+
+
+
+
+ bind
+ org.springframework.web.servlet.tags.BindTag
+ JSP
+
+
+ Provides BindStatus object for the given bind path.
+ The HTML escaping flag participates in a page-wide or application-wide setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+
+
+
+ status
+ org.springframework.web.servlet.support.BindStatus
+
+
+
+ path
+ true
+ true
+
+
+
+ ignoreNestedPath
+ false
+ true
+
+
+
+ htmlEscape
+ false
+ true
+
+
+
+
+
+
+
+ transform
+ org.springframework.web.servlet.tags.TransformTag
+ JSP
+
+
+ Provides transformation of variables to Strings, using an appropriate
+ custom PropertyEditor from BindTag (can only be used inside BindTag).
+ The HTML escaping flag participates in a page-wide or application-wide setting
+ (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+
+
+
+ value
+ true
+ true
+
+
+
+ var
+ false
+ true
+
+
+
+ scope
+ false
+ true
+
+
+
+ htmlEscape
+ false
+ true
+
+
+
+
+
diff --git a/ch09/ch10/demo-grails/web-app/css/errors.css b/ch09/ch10/demo-grails/web-app/css/errors.css
new file mode 100644
index 0000000..bdb58bc
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/css/errors.css
@@ -0,0 +1,109 @@
+h1, h2 {
+ margin: 10px 25px 5px;
+}
+
+h2 {
+ font-size: 1.1em;
+}
+
+.filename {
+ font-style: italic;
+}
+
+.exceptionMessage {
+ margin: 10px;
+ border: 1px solid #000;
+ padding: 5px;
+ background-color: #E9E9E9;
+}
+
+.stack,
+.snippet {
+ margin: 0 25px 10px;
+}
+
+.stack,
+.snippet {
+ border: 1px solid #ccc;
+ -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ box-shadow: 0 0 2px rgba(0,0,0,0.2);
+}
+
+/* error details */
+.error-details {
+ border-top: 1px solid #FFAAAA;
+ -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ border-bottom: 1px solid #FFAAAA;
+ -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ box-shadow: 0 0 2px rgba(0,0,0,0.2);
+ background-color:#FFF3F3;
+ line-height: 1.5;
+ overflow: hidden;
+ padding: 5px;
+ padding-left:25px;
+}
+
+.error-details dt {
+ clear: left;
+ float: left;
+ font-weight: bold;
+ margin-right: 5px;
+}
+
+.error-details dt:after {
+ content: ":";
+}
+
+.error-details dd {
+ display: block;
+}
+
+/* stack trace */
+.stack {
+ padding: 5px;
+ overflow: auto;
+ height: 150px;
+}
+
+/* code snippet */
+.snippet {
+ background-color: #fff;
+ font-family: monospace;
+}
+
+.snippet .line {
+ display: block;
+}
+
+.snippet .lineNumber {
+ background-color: #ddd;
+ color: #999;
+ display: inline-block;
+ margin-right: 5px;
+ padding: 0 3px;
+ text-align: right;
+ width: 3em;
+}
+
+.snippet .error {
+ background-color: #fff3f3;
+ font-weight: bold;
+}
+
+.snippet .error .lineNumber {
+ background-color: #faa;
+ color: #333;
+ font-weight: bold;
+}
+
+.snippet .line:first-child .lineNumber {
+ padding-top: 5px;
+}
+
+.snippet .line:last-child .lineNumber {
+ padding-bottom: 5px;
+}
\ No newline at end of file
diff --git a/ch09/ch10/demo-grails/web-app/css/main.css b/ch09/ch10/demo-grails/web-app/css/main.css
new file mode 100644
index 0000000..a55945d
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/css/main.css
@@ -0,0 +1,596 @@
+/* FONT STACK */
+body,
+input, select, textarea {
+ font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ line-height: 1.1;
+}
+
+/* BASE LAYOUT */
+
+html {
+ background-color: #ddd;
+ background-image: -moz-linear-gradient(center top, #aaa, #ddd);
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #aaa), color-stop(1, #ddd));
+ background-image: linear-gradient(top, #aaa, #ddd);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorStr = '#aaaaaa', EndColorStr = '#dddddd');
+ background-repeat: no-repeat;
+ height: 100%;
+ /* change the box model to exclude the padding from the calculation of 100% height (IE8+) */
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+html.no-cssgradients {
+ background-color: #aaa;
+}
+
+.ie6 html {
+ height: 100%;
+}
+
+html * {
+ margin: 0;
+}
+
+body {
+ background: #ffffff;
+ color: #333333;
+ margin: 0 auto;
+ max-width: 960px;
+ overflow-x: hidden; /* prevents box-shadow causing a horizontal scrollbar in firefox when viewport < 960px wide */
+ -moz-box-shadow: 0 0 0.3em #255b17;
+ -webkit-box-shadow: 0 0 0.3em #255b17;
+ box-shadow: 0 0 0.3em #255b17;
+}
+
+#grailsLogo {
+ background-color: #abbf78;
+}
+
+/* replace with .no-boxshadow body if you have modernizr available */
+.ie6 body,
+.ie7 body,
+.ie8 body {
+ border-color: #255b17;
+ border-style: solid;
+ border-width: 0 1px;
+}
+
+.ie6 body {
+ height: 100%;
+}
+
+a:link, a:visited, a:hover {
+ color: #48802c;
+}
+
+a:hover, a:active {
+ outline: none; /* prevents outline in webkit on active links but retains it for tab focus */
+}
+
+h1 {
+ color: #48802c;
+ font-weight: normal;
+ font-size: 1.25em;
+ margin: 0.8em 0 0.3em 0;
+}
+
+ul {
+ padding: 0;
+}
+
+img {
+ border: 0;
+}
+
+/* GENERAL */
+
+#grailsLogo a {
+ display: inline-block;
+ margin: 1em;
+}
+
+.content {
+}
+
+.content h1 {
+ border-bottom: 1px solid #CCCCCC;
+ margin: 0.8em 1em 0.3em;
+ padding: 0 0.25em;
+}
+
+.scaffold-list h1 {
+ border: none;
+}
+
+.footer {
+ background: #abbf78;
+ color: #000;
+ clear: both;
+ font-size: 0.8em;
+ margin-top: 1.5em;
+ padding: 1em;
+ min-height: 1em;
+}
+
+.footer a {
+ color: #255b17;
+}
+
+.spinner {
+ background: url(../images/spinner.gif) 50% 50% no-repeat transparent;
+ height: 16px;
+ width: 16px;
+ padding: 0.5em;
+ position: absolute;
+ right: 0;
+ top: 0;
+ text-indent: -9999px;
+}
+
+/* NAVIGATION MENU */
+
+.nav {
+ background-color: #efefef;
+ padding: 0.5em 0.75em;
+ -moz-box-shadow: 0 0 3px 1px #aaaaaa;
+ -webkit-box-shadow: 0 0 3px 1px #aaaaaa;
+ box-shadow: 0 0 3px 1px #aaaaaa;
+ zoom: 1;
+}
+
+.nav ul {
+ overflow: hidden;
+ padding-left: 0;
+ zoom: 1;
+}
+
+.nav li {
+ display: block;
+ float: left;
+ list-style-type: none;
+ margin-right: 0.5em;
+ padding: 0;
+}
+
+.nav a {
+ color: #666666;
+ display: block;
+ padding: 0.25em 0.7em;
+ text-decoration: none;
+ -moz-border-radius: 0.3em;
+ -webkit-border-radius: 0.3em;
+ border-radius: 0.3em;
+}
+
+.nav a:active, .nav a:visited {
+ color: #666666;
+}
+
+.nav a:focus, .nav a:hover {
+ background-color: #999999;
+ color: #ffffff;
+ outline: none;
+ text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
+}
+
+.no-borderradius .nav a:focus, .no-borderradius .nav a:hover {
+ background-color: transparent;
+ color: #444444;
+ text-decoration: underline;
+}
+
+.nav a.home, .nav a.list, .nav a.create {
+ background-position: 0.7em center;
+ background-repeat: no-repeat;
+ text-indent: 25px;
+}
+
+.nav a.home {
+ background-image: url(../images/skin/house.png);
+}
+
+.nav a.list {
+ background-image: url(../images/skin/database_table.png);
+}
+
+.nav a.create {
+ background-image: url(../images/skin/database_add.png);
+}
+
+/* CREATE/EDIT FORMS AND SHOW PAGES */
+
+fieldset,
+.property-list {
+ margin: 0.6em 1.25em 0 1.25em;
+ padding: 0.3em 1.8em 1.25em;
+ position: relative;
+ zoom: 1;
+ border: none;
+}
+
+.property-list .fieldcontain {
+ list-style: none;
+ overflow: hidden;
+ zoom: 1;
+}
+
+.fieldcontain {
+ margin-top: 1em;
+}
+
+.fieldcontain label,
+.fieldcontain .property-label {
+ color: #666666;
+ text-align: right;
+ width: 25%;
+}
+
+.fieldcontain .property-label {
+ float: left;
+}
+
+.fieldcontain .property-value {
+ display: block;
+ margin-left: 27%;
+}
+
+label {
+ cursor: pointer;
+ display: inline-block;
+ margin: 0 0.25em 0 0;
+}
+
+input, select, textarea {
+ background-color: #fcfcfc;
+ border: 1px solid #cccccc;
+ font-size: 1em;
+ padding: 0.2em 0.4em;
+}
+
+select {
+ padding: 0.2em 0.2em 0.2em 0;
+}
+
+select[multiple] {
+ vertical-align: top;
+}
+
+textarea {
+ width: 250px;
+ height: 150px;
+ overflow: auto; /* IE always renders vertical scrollbar without this */
+ vertical-align: top;
+}
+
+input[type=checkbox], input[type=radio] {
+ background-color: transparent;
+ border: 0;
+ padding: 0;
+}
+
+input:focus, select:focus, textarea:focus {
+ background-color: #ffffff;
+ border: 1px solid #eeeeee;
+ outline: 0;
+ -moz-box-shadow: 0 0 0.5em #ffffff;
+ -webkit-box-shadow: 0 0 0.5em #ffffff;
+ box-shadow: 0 0 0.5em #ffffff;
+}
+
+.required-indicator {
+ color: #48802C;
+ display: inline-block;
+ font-weight: bold;
+ margin-left: 0.3em;
+ position: relative;
+ top: 0.1em;
+}
+
+ul.one-to-many {
+ display: inline-block;
+ list-style-position: inside;
+ vertical-align: top;
+}
+
+.ie6 ul.one-to-many, .ie7 ul.one-to-many {
+ display: inline;
+ zoom: 1;
+}
+
+ul.one-to-many li.add {
+ list-style-type: none;
+}
+
+/* EMBEDDED PROPERTIES */
+
+fieldset.embedded {
+ background-color: transparent;
+ border: 1px solid #CCCCCC;
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 0;
+ padding-right: 0;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+fieldset.embedded legend {
+ margin: 0 1em;
+}
+
+/* MESSAGES AND ERRORS */
+
+.errors,
+.message {
+ font-size: 0.8em;
+ line-height: 2;
+ margin: 1em 2em;
+ padding: 0.25em;
+}
+
+.message {
+ background: #f3f3ff;
+ border: 1px solid #b2d1ff;
+ color: #006dba;
+ -moz-box-shadow: 0 0 0.25em #b2d1ff;
+ -webkit-box-shadow: 0 0 0.25em #b2d1ff;
+ box-shadow: 0 0 0.25em #b2d1ff;
+}
+
+.errors {
+ background: #fff3f3;
+ border: 1px solid #ffaaaa;
+ color: #cc0000;
+ -moz-box-shadow: 0 0 0.25em #ff8888;
+ -webkit-box-shadow: 0 0 0.25em #ff8888;
+ box-shadow: 0 0 0.25em #ff8888;
+}
+
+.errors ul,
+.message {
+ padding: 0;
+}
+
+.errors li {
+ list-style: none;
+ background: transparent url(../images/skin/exclamation.png) 0.5em 50% no-repeat;
+ text-indent: 2.2em;
+}
+
+.message {
+ background: transparent url(../images/skin/information.png) 0.5em 50% no-repeat;
+ text-indent: 2.2em;
+}
+
+/* form fields with errors */
+
+.error input, .error select, .error textarea {
+ background: #fff3f3;
+ border-color: #ffaaaa;
+ color: #cc0000;
+}
+
+.error input:focus, .error select:focus, .error textarea:focus {
+ -moz-box-shadow: 0 0 0.5em #ffaaaa;
+ -webkit-box-shadow: 0 0 0.5em #ffaaaa;
+ box-shadow: 0 0 0.5em #ffaaaa;
+}
+
+/* same effects for browsers that support HTML5 client-side validation (these have to be specified separately or IE will ignore the entire rule) */
+
+input:invalid, select:invalid, textarea:invalid {
+ background: #fff3f3;
+ border-color: #ffaaaa;
+ color: #cc0000;
+}
+
+input:invalid:focus, select:invalid:focus, textarea:invalid:focus {
+ -moz-box-shadow: 0 0 0.5em #ffaaaa;
+ -webkit-box-shadow: 0 0 0.5em #ffaaaa;
+ box-shadow: 0 0 0.5em #ffaaaa;
+}
+
+/* TABLES */
+
+table {
+ border-top: 1px solid #DFDFDF;
+ border-collapse: collapse;
+ width: 100%;
+ margin-bottom: 1em;
+}
+
+tr {
+ border: 0;
+}
+
+tr>td:first-child, tr>th:first-child {
+ padding-left: 1.25em;
+}
+
+tr>td:last-child, tr>th:last-child {
+ padding-right: 1.25em;
+}
+
+td, th {
+ line-height: 1.5em;
+ padding: 0.5em 0.6em;
+ text-align: left;
+ vertical-align: top;
+}
+
+th {
+ background-color: #efefef;
+ background-image: -moz-linear-gradient(top, #ffffff, #eaeaea);
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ffffff), color-stop(1, #eaeaea));
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorStr = '#ffffff', EndColorStr = '#eaeaea');
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#eaeaea')";
+ color: #666666;
+ font-weight: bold;
+ line-height: 1.7em;
+ padding: 0.2em 0.6em;
+}
+
+thead th {
+ white-space: nowrap;
+}
+
+th a {
+ display: block;
+ text-decoration: none;
+}
+
+th a:link, th a:visited {
+ color: #666666;
+}
+
+th a:hover, th a:focus {
+ color: #333333;
+}
+
+th.sortable a {
+ background-position: right;
+ background-repeat: no-repeat;
+ padding-right: 1.1em;
+}
+
+th.asc a {
+ background-image: url(../images/skin/sorted_asc.gif);
+}
+
+th.desc a {
+ background-image: url(../images/skin/sorted_desc.gif);
+}
+
+.odd {
+ background: #f7f7f7;
+}
+
+.even {
+ background: #ffffff;
+}
+
+th:hover, tr:hover {
+ background: #E1F2B6;
+}
+
+/* PAGINATION */
+
+.pagination {
+ border-top: 0;
+ margin: 0;
+ padding: 0.3em 0.2em;
+ text-align: center;
+ -moz-box-shadow: 0 0 3px 1px #AAAAAA;
+ -webkit-box-shadow: 0 0 3px 1px #AAAAAA;
+ box-shadow: 0 0 3px 1px #AAAAAA;
+ background-color: #EFEFEF;
+}
+
+.pagination a,
+.pagination .currentStep {
+ color: #666666;
+ display: inline-block;
+ margin: 0 0.1em;
+ padding: 0.25em 0.7em;
+ text-decoration: none;
+ -moz-border-radius: 0.3em;
+ -webkit-border-radius: 0.3em;
+ border-radius: 0.3em;
+}
+
+.pagination a:hover, .pagination a:focus,
+.pagination .currentStep {
+ background-color: #999999;
+ color: #ffffff;
+ outline: none;
+ text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
+}
+
+.no-borderradius .pagination a:hover, .no-borderradius .pagination a:focus,
+.no-borderradius .pagination .currentStep {
+ background-color: transparent;
+ color: #444444;
+ text-decoration: underline;
+}
+
+/* ACTION BUTTONS */
+
+.buttons {
+ background-color: #efefef;
+ overflow: hidden;
+ padding: 0.3em;
+ -moz-box-shadow: 0 0 3px 1px #aaaaaa;
+ -webkit-box-shadow: 0 0 3px 1px #aaaaaa;
+ box-shadow: 0 0 3px 1px #aaaaaa;
+ margin: 0.1em 0 0 0;
+ border: none;
+}
+
+.buttons input,
+.buttons a {
+ background-color: transparent;
+ border: 0;
+ color: #666666;
+ cursor: pointer;
+ display: inline-block;
+ margin: 0 0.25em 0;
+ overflow: visible;
+ padding: 0.25em 0.7em;
+ text-decoration: none;
+
+ -moz-border-radius: 0.3em;
+ -webkit-border-radius: 0.3em;
+ border-radius: 0.3em;
+}
+
+.buttons input:hover, .buttons input:focus,
+.buttons a:hover, .buttons a:focus {
+ background-color: #999999;
+ color: #ffffff;
+ outline: none;
+ text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+.no-borderradius .buttons input:hover, .no-borderradius .buttons input:focus,
+.no-borderradius .buttons a:hover, .no-borderradius .buttons a:focus {
+ background-color: transparent;
+ color: #444444;
+ text-decoration: underline;
+}
+
+.buttons .delete, .buttons .edit, .buttons .save {
+ background-position: 0.7em center;
+ background-repeat: no-repeat;
+ text-indent: 25px;
+}
+
+.ie6 .buttons input.delete, .ie6 .buttons input.edit, .ie6 .buttons input.save,
+.ie7 .buttons input.delete, .ie7 .buttons input.edit, .ie7 .buttons input.save {
+ padding-left: 36px;
+}
+
+.buttons .delete {
+ background-image: url(../images/skin/database_delete.png);
+}
+
+.buttons .edit {
+ background-image: url(../images/skin/database_edit.png);
+}
+
+.buttons .save {
+ background-image: url(../images/skin/database_save.png);
+}
+
+a.skip {
+ position: absolute;
+ left: -9999px;
+}
diff --git a/ch09/ch10/demo-grails/web-app/css/mobile.css b/ch09/ch10/demo-grails/web-app/css/mobile.css
new file mode 100644
index 0000000..167f502
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/css/mobile.css
@@ -0,0 +1,82 @@
+/* Styles for mobile devices */
+
+@media screen and (max-width: 480px) {
+ .nav {
+ padding: 0.5em;
+ }
+
+ .nav li {
+ margin: 0 0.5em 0 0;
+ padding: 0.25em;
+ }
+
+ /* Hide individual steps in pagination, just have next & previous */
+ .pagination .step, .pagination .currentStep {
+ display: none;
+ }
+
+ .pagination .prevLink {
+ float: left;
+ }
+
+ .pagination .nextLink {
+ float: right;
+ }
+
+ /* pagination needs to wrap around floated buttons */
+ .pagination {
+ overflow: hidden;
+ }
+
+ /* slightly smaller margin around content body */
+ fieldset,
+ .property-list {
+ padding: 0.3em 1em 1em;
+ }
+
+ input, textarea {
+ width: 100%;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+
+ select, input[type=checkbox], input[type=radio], input[type=submit], input[type=button], input[type=reset] {
+ width: auto;
+ }
+
+ /* hide all but the first column of list tables */
+ .scaffold-list td:not(:first-child),
+ .scaffold-list th:not(:first-child) {
+ display: none;
+ }
+
+ .scaffold-list thead th {
+ text-align: center;
+ }
+
+ /* stack form elements */
+ .fieldcontain {
+ margin-top: 0.6em;
+ }
+
+ .fieldcontain label,
+ .fieldcontain .property-label,
+ .fieldcontain .property-value {
+ display: block;
+ float: none;
+ margin: 0 0 0.25em 0;
+ text-align: left;
+ width: auto;
+ }
+
+ .errors ul,
+ .message p {
+ margin: 0.5em;
+ }
+
+ .error ul {
+ margin-left: 0;
+ }
+}
diff --git a/ch09/ch10/demo-grails/web-app/images/apple-touch-icon-retina.png b/ch09/ch10/demo-grails/web-app/images/apple-touch-icon-retina.png
new file mode 100644
index 0000000..5cc83ed
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/apple-touch-icon-retina.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/apple-touch-icon.png b/ch09/ch10/demo-grails/web-app/images/apple-touch-icon.png
new file mode 100644
index 0000000..aba337f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/apple-touch-icon.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/favicon.ico b/ch09/ch10/demo-grails/web-app/images/favicon.ico
new file mode 100644
index 0000000..3dfcb92
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/favicon.ico differ
diff --git a/ch09/ch10/demo-grails/web-app/images/grails_logo.jpg b/ch09/ch10/demo-grails/web-app/images/grails_logo.jpg
new file mode 100644
index 0000000..8be657c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/grails_logo.jpg differ
diff --git a/ch09/ch10/demo-grails/web-app/images/grails_logo.png b/ch09/ch10/demo-grails/web-app/images/grails_logo.png
new file mode 100644
index 0000000..9836b93
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/grails_logo.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/leftnav_btm.png b/ch09/ch10/demo-grails/web-app/images/leftnav_btm.png
new file mode 100644
index 0000000..582e1eb
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/leftnav_btm.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/leftnav_midstretch.png b/ch09/ch10/demo-grails/web-app/images/leftnav_midstretch.png
new file mode 100644
index 0000000..3cb8a51
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/leftnav_midstretch.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/leftnav_top.png b/ch09/ch10/demo-grails/web-app/images/leftnav_top.png
new file mode 100644
index 0000000..6afec7d
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/leftnav_top.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/database_add.png b/ch09/ch10/demo-grails/web-app/images/skin/database_add.png
new file mode 100644
index 0000000..802bd6c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/database_add.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/database_delete.png b/ch09/ch10/demo-grails/web-app/images/skin/database_delete.png
new file mode 100644
index 0000000..cce652e
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/database_delete.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/database_edit.png b/ch09/ch10/demo-grails/web-app/images/skin/database_edit.png
new file mode 100644
index 0000000..e501b66
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/database_edit.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/database_save.png b/ch09/ch10/demo-grails/web-app/images/skin/database_save.png
new file mode 100644
index 0000000..44c06dd
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/database_save.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/database_table.png b/ch09/ch10/demo-grails/web-app/images/skin/database_table.png
new file mode 100644
index 0000000..693709c
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/database_table.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/exclamation.png b/ch09/ch10/demo-grails/web-app/images/skin/exclamation.png
new file mode 100644
index 0000000..c37bd06
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/exclamation.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/house.png b/ch09/ch10/demo-grails/web-app/images/skin/house.png
new file mode 100644
index 0000000..fed6221
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/house.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/information.png b/ch09/ch10/demo-grails/web-app/images/skin/information.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/information.png differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/shadow.jpg b/ch09/ch10/demo-grails/web-app/images/skin/shadow.jpg
new file mode 100644
index 0000000..b7ed44f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/shadow.jpg differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/sorted_asc.gif b/ch09/ch10/demo-grails/web-app/images/skin/sorted_asc.gif
new file mode 100644
index 0000000..6b179c1
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/sorted_asc.gif differ
diff --git a/ch09/ch10/demo-grails/web-app/images/skin/sorted_desc.gif b/ch09/ch10/demo-grails/web-app/images/skin/sorted_desc.gif
new file mode 100644
index 0000000..38b3a01
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/skin/sorted_desc.gif differ
diff --git a/ch09/ch10/demo-grails/web-app/images/spinner.gif b/ch09/ch10/demo-grails/web-app/images/spinner.gif
new file mode 100644
index 0000000..1ed786f
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/spinner.gif differ
diff --git a/ch09/ch10/demo-grails/web-app/images/springsource.png b/ch09/ch10/demo-grails/web-app/images/springsource.png
new file mode 100644
index 0000000..e806d00
Binary files /dev/null and b/ch09/ch10/demo-grails/web-app/images/springsource.png differ
diff --git a/ch09/ch10/demo-grails/web-app/js/application.js b/ch09/ch10/demo-grails/web-app/js/application.js
new file mode 100644
index 0000000..b2adb96
--- /dev/null
+++ b/ch09/ch10/demo-grails/web-app/js/application.js
@@ -0,0 +1,9 @@
+if (typeof jQuery !== 'undefined') {
+ (function($) {
+ $('#spinner').ajaxStart(function() {
+ $(this).fadeIn();
+ }).ajaxStop(function() {
+ $(this).fadeOut();
+ });
+ })(jQuery);
+}
diff --git a/ch09/ch10/demo/.gitignore b/ch09/ch10/demo/.gitignore
new file mode 100644
index 0000000..eb3489a
--- /dev/null
+++ b/ch09/ch10/demo/.gitignore
@@ -0,0 +1,15 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile ~/.gitignore_global
+
+# Ignore bundler config
+/.bundle
+
+# Ignore the default SQLite database.
+/db/*.sqlite3
+
+# Ignore all logfiles and tempfiles.
+/log/*.log
+/tmp
diff --git a/ch09/ch10/demo/.idea/.generators b/ch09/ch10/demo/.idea/.generators
new file mode 100644
index 0000000..4926284
--- /dev/null
+++ b/ch09/ch10/demo/.idea/.generators
@@ -0,0 +1,8 @@
+
+
diff --git a/ch09/ch10/demo/.idea/.name b/ch09/ch10/demo/.idea/.name
new file mode 100644
index 0000000..efd261b
--- /dev/null
+++ b/ch09/ch10/demo/.idea/.name
@@ -0,0 +1 @@
+demo
\ No newline at end of file
diff --git a/ch09/ch10/demo/.idea/.rakeTasks b/ch09/ch10/demo/.idea/.rakeTasks
new file mode 100644
index 0000000..a31cdd0
--- /dev/null
+++ b/ch09/ch10/demo/.idea/.rakeTasks
@@ -0,0 +1,7 @@
+
+
diff --git a/ch09/ch10/demo/.idea/demo.iml b/ch09/ch10/demo/.idea/demo.iml
new file mode 100644
index 0000000..9bf6795
--- /dev/null
+++ b/ch09/ch10/demo/.idea/demo.iml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo/.idea/encodings.xml b/ch09/ch10/demo/.idea/encodings.xml
new file mode 100644
index 0000000..e206d70
--- /dev/null
+++ b/ch09/ch10/demo/.idea/encodings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/ch09/ch10/demo/.idea/misc.xml b/ch09/ch10/demo/.idea/misc.xml
new file mode 100644
index 0000000..3b2f328
--- /dev/null
+++ b/ch09/ch10/demo/.idea/misc.xml
@@ -0,0 +1,8 @@
+
+
+
+ $APPLICATION_HOME_DIR$/lib/rubymine.jar!/resources/html5-schema/html5.rnc
+
+
+
+
diff --git a/ch09/ch10/demo/.idea/modules.xml b/ch09/ch10/demo/.idea/modules.xml
new file mode 100644
index 0000000..7d39e3e
--- /dev/null
+++ b/ch09/ch10/demo/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo/.idea/scopes/scope_settings.xml b/ch09/ch10/demo/.idea/scopes/scope_settings.xml
new file mode 100644
index 0000000..922003b
--- /dev/null
+++ b/ch09/ch10/demo/.idea/scopes/scope_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ch09/ch10/demo/.idea/vcs.xml b/ch09/ch10/demo/.idea/vcs.xml
new file mode 100644
index 0000000..def6a6a
--- /dev/null
+++ b/ch09/ch10/demo/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo/.idea/workspace.xml b/ch09/ch10/demo/.idea/workspace.xml
new file mode 100644
index 0000000..4cb2836
--- /dev/null
+++ b/ch09/ch10/demo/.idea/workspace.xml
@@ -0,0 +1,611 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+ 1349623479320
+ 1349623479320
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo/Gemfile b/ch09/ch10/demo/Gemfile
new file mode 100644
index 0000000..cb2ec41
--- /dev/null
+++ b/ch09/ch10/demo/Gemfile
@@ -0,0 +1,39 @@
+source 'https://rubygems.org'
+
+gem 'rails', '3.2.8'
+
+# Bundle edge Rails instead:
+# gem 'rails', :git => 'git://github.com/rails/rails.git'
+
+gem 'activerecord-jdbcsqlite3-adapter'
+
+gem 'jruby-openssl'
+
+# Gems used only for assets and not required
+# in production environments by default.
+group :assets do
+ gem 'sass-rails', '~> 3.2.3'
+ gem 'coffee-rails', '~> 3.2.1'
+
+ # See https://github.com/sstephenson/execjs#readme for more supported runtimes
+ gem 'therubyrhino'
+
+ gem 'uglifier', '>= 1.0.3'
+end
+
+gem 'jquery-rails'
+
+# To use ActiveModel has_secure_password
+# gem 'bcrypt-ruby', '~> 3.0.0'
+
+# To use Jbuilder templates for JSON
+# gem 'jbuilder'
+
+# Use unicorn as the app server
+# gem 'unicorn'
+
+# Deploy with Capistrano
+# gem 'capistrano'
+
+# To use debugger
+# gem 'debugger'
diff --git a/ch09/ch10/demo/Gemfile.lock b/ch09/ch10/demo/Gemfile.lock
new file mode 100644
index 0000000..83dfe3a
--- /dev/null
+++ b/ch09/ch10/demo/Gemfile.lock
@@ -0,0 +1,123 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actionmailer (3.2.8)
+ actionpack (= 3.2.8)
+ mail (~> 2.4.4)
+ actionpack (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.4)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.3)
+ activemodel (3.2.8)
+ activesupport (= 3.2.8)
+ builder (~> 3.0.0)
+ activerecord (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activerecord-jdbc-adapter (1.2.2)
+ activerecord-jdbcsqlite3-adapter (1.2.2)
+ activerecord-jdbc-adapter (~> 1.2.2)
+ jdbc-sqlite3 (~> 3.7.2)
+ activeresource (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ activesupport (3.2.8)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+ arel (3.0.2)
+ bouncy-castle-java (1.5.0146.1)
+ builder (3.0.3)
+ coffee-rails (3.2.2)
+ coffee-script (>= 2.2.0)
+ railties (~> 3.2.0)
+ coffee-script (2.2.0)
+ coffee-script-source
+ execjs
+ coffee-script-source (1.3.3)
+ erubis (2.7.0)
+ execjs (1.4.0)
+ multi_json (~> 1.0)
+ hike (1.2.1)
+ i18n (0.6.1)
+ jdbc-sqlite3 (3.7.2)
+ journey (1.0.4)
+ jquery-rails (2.1.3)
+ railties (>= 3.1.0, < 5.0)
+ thor (~> 0.14)
+ jruby-openssl (0.7.7)
+ bouncy-castle-java (>= 1.5.0146.1)
+ json (1.7.5-java)
+ mail (2.4.4)
+ i18n (>= 0.4.0)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ mime-types (1.19)
+ multi_json (1.3.6)
+ polyglot (0.3.3)
+ rack (1.4.1)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-ssl (1.3.2)
+ rack
+ rack-test (0.6.2)
+ rack (>= 1.0)
+ rails (3.2.8)
+ actionmailer (= 3.2.8)
+ actionpack (= 3.2.8)
+ activerecord (= 3.2.8)
+ activeresource (= 3.2.8)
+ activesupport (= 3.2.8)
+ bundler (~> 1.0)
+ railties (= 3.2.8)
+ railties (3.2.8)
+ actionpack (= 3.2.8)
+ activesupport (= 3.2.8)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (>= 0.14.6, < 2.0)
+ rake (0.9.2.2)
+ rdoc (3.12)
+ json (~> 1.4)
+ sass (3.2.1)
+ sass-rails (3.2.5)
+ railties (~> 3.2.0)
+ sass (>= 3.1.10)
+ tilt (~> 1.3)
+ sprockets (2.1.3)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ therubyrhino (2.0.1)
+ therubyrhino_jar (>= 1.7.3)
+ therubyrhino_jar (1.7.4)
+ thor (0.16.0)
+ tilt (1.3.3)
+ treetop (1.4.10)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.33)
+ uglifier (1.3.0)
+ execjs (>= 0.3.0)
+ multi_json (~> 1.0, >= 1.0.2)
+
+PLATFORMS
+ java
+
+DEPENDENCIES
+ activerecord-jdbcsqlite3-adapter
+ coffee-rails (~> 3.2.1)
+ jquery-rails
+ jruby-openssl
+ rails (= 3.2.8)
+ sass-rails (~> 3.2.3)
+ therubyrhino
+ uglifier (>= 1.0.3)
diff --git a/ch09/ch10/demo/README.rdoc b/ch09/ch10/demo/README.rdoc
new file mode 100644
index 0000000..7c36f23
--- /dev/null
+++ b/ch09/ch10/demo/README.rdoc
@@ -0,0 +1,261 @@
+== Welcome to Rails
+
+Rails is a web-application framework that includes everything needed to create
+database-backed web applications according to the Model-View-Control pattern.
+
+This pattern splits the view (also called the presentation) into "dumb"
+templates that are primarily responsible for inserting pre-built data in between
+HTML tags. The model contains the "smart" domain objects (such as Account,
+Product, Person, Post) that holds all the business logic and knows how to
+persist themselves to a database. The controller handles the incoming requests
+(such as Save New Account, Update Product, Show Post) by manipulating the model
+and directing data to the view.
+
+In Rails, the model is handled by what's called an object-relational mapping
+layer entitled Active Record. This layer allows you to present the data from
+database rows as objects and embellish these data objects with business logic
+methods. You can read more about Active Record in
+link:files/vendor/rails/activerecord/README.html.
+
+The controller and view are handled by the Action Pack, which handles both
+layers by its two parts: Action View and Action Controller. These two layers
+are bundled in a single package due to their heavy interdependence. This is
+unlike the relationship between the Active Record and Action Pack that is much
+more separate. Each of these packages can be used independently outside of
+Rails. You can read more about Action Pack in
+link:files/vendor/rails/actionpack/README.html.
+
+
+== Getting Started
+
+1. At the command prompt, create a new Rails application:
+ rails new myapp (where myapp is the application name)
+
+2. Change directory to myapp and start the web server:
+ cd myapp; rails server (run with --help for options)
+
+3. Go to http://localhost:3000/ and you'll see:
+ "Welcome aboard: You're riding Ruby on Rails!"
+
+4. Follow the guidelines to start developing your application. You can find
+the following resources handy:
+
+* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
+* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
+
+
+== Debugging Rails
+
+Sometimes your application goes wrong. Fortunately there are a lot of tools that
+will help you debug it and get it back on the rails.
+
+First area to check is the application log files. Have "tail -f" commands
+running on the server.log and development.log. Rails will automatically display
+debugging and runtime information to these files. Debugging info will also be
+shown in the browser on requests from 127.0.0.1.
+
+You can also log your own messages directly into the log file from your code
+using the Ruby logger class from inside your controllers. Example:
+
+ class WeblogController < ActionController::Base
+ def destroy
+ @weblog = Weblog.find(params[:id])
+ @weblog.destroy
+ logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
+ end
+ end
+
+The result will be a message in your log file along the lines of:
+
+ Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
+
+More information on how to use the logger is at http://www.ruby-doc.org/core/
+
+Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
+several books available online as well:
+
+* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
+* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
+
+These two books will bring you up to speed on the Ruby language and also on
+programming in general.
+
+
+== Debugger
+
+Debugger support is available through the debugger command when you start your
+Mongrel or WEBrick server with --debugger. This means that you can break out of
+execution at any point in the code, investigate and change the model, and then,
+resume execution! You need to install ruby-debug to run the server in debugging
+mode. With gems, use sudo gem install ruby-debug . Example:
+
+ class WeblogController < ActionController::Base
+ def index
+ @posts = Post.all
+ debugger
+ end
+ end
+
+So the controller will accept the action, run the first line, then present you
+with a IRB prompt in the server window. Here you can do things like:
+
+ >> @posts.inspect
+ => "[#nil, "body"=>nil, "id"=>"1"}>,
+ #"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
+ >> @posts.first.title = "hello from a debugger"
+ => "hello from a debugger"
+
+...and even better, you can examine how your runtime objects actually work:
+
+ >> f = @posts.first
+ => #nil, "body"=>nil, "id"=>"1"}>
+ >> f.
+ Display all 152 possibilities? (y or n)
+
+Finally, when you're ready to resume execution, you can enter "cont".
+
+
+== Console
+
+The console is a Ruby shell, which allows you to interact with your
+application's domain model. Here you'll have all parts of the application
+configured, just like it is when the application is running. You can inspect
+domain models, change values, and save to the database. Starting the script
+without arguments will launch it in the development environment.
+
+To start the console, run rails console from the application
+directory.
+
+Options:
+
+* Passing the -s, --sandbox argument will rollback any modifications
+ made to the database.
+* Passing an environment name as an argument will load the corresponding
+ environment. Example: rails console production .
+
+To reload your controllers and models after launching the console run
+reload!
+
+More information about irb can be found at:
+link:http://www.rubycentral.org/pickaxe/irb.html
+
+
+== dbconsole
+
+You can go to the command line of your database directly through rails
+dbconsole . You would be connected to the database with the credentials
+defined in database.yml. Starting the script without arguments will connect you
+to the development database. Passing an argument will connect you to a different
+database, like rails dbconsole production . Currently works for MySQL,
+PostgreSQL and SQLite 3.
+
+== Description of Contents
+
+The default directory structure of a generated Ruby on Rails application:
+
+ |-- app
+ | |-- assets
+ | |-- images
+ | |-- javascripts
+ | `-- stylesheets
+ | |-- controllers
+ | |-- helpers
+ | |-- mailers
+ | |-- models
+ | `-- views
+ | `-- layouts
+ |-- config
+ | |-- environments
+ | |-- initializers
+ | `-- locales
+ |-- db
+ |-- doc
+ |-- lib
+ | `-- tasks
+ |-- log
+ |-- public
+ |-- script
+ |-- test
+ | |-- fixtures
+ | |-- functional
+ | |-- integration
+ | |-- performance
+ | `-- unit
+ |-- tmp
+ | |-- cache
+ | |-- pids
+ | |-- sessions
+ | `-- sockets
+ `-- vendor
+ |-- assets
+ `-- stylesheets
+ `-- plugins
+
+app
+ Holds all the code that's specific to this particular application.
+
+app/assets
+ Contains subdirectories for images, stylesheets, and JavaScript files.
+
+app/controllers
+ Holds controllers that should be named like weblogs_controller.rb for
+ automated URL mapping. All controllers should descend from
+ ApplicationController which itself descends from ActionController::Base.
+
+app/models
+ Holds models that should be named like post.rb. Models descend from
+ ActiveRecord::Base by default.
+
+app/views
+ Holds the template files for the view that should be named like
+ weblogs/index.html.erb for the WeblogsController#index action. All views use
+ eRuby syntax by default.
+
+app/views/layouts
+ Holds the template files for layouts to be used with views. This models the
+ common header/footer method of wrapping views. In your views, define a layout
+ using the layout :default and create a file named default.html.erb.
+ Inside default.html.erb, call <% yield %> to render the view using this
+ layout.
+
+app/helpers
+ Holds view helpers that should be named like weblogs_helper.rb. These are
+ generated for you automatically when using generators for controllers.
+ Helpers can be used to wrap functionality for your views into methods.
+
+config
+ Configuration files for the Rails environment, the routing map, the database,
+ and other dependencies.
+
+db
+ Contains the database schema in schema.rb. db/migrate contains all the
+ sequence of Migrations for your schema.
+
+doc
+ This directory is where your application documentation will be stored when
+ generated using rake doc:app
+
+lib
+ Application specific libraries. Basically, any kind of custom code that
+ doesn't belong under controllers, models, or helpers. This directory is in
+ the load path.
+
+public
+ The directory available for the web server. Also contains the dispatchers and the
+ default HTML files. This should be set as the DOCUMENT_ROOT of your web
+ server.
+
+script
+ Helper scripts for automation and generation.
+
+test
+ Unit and functional tests along with fixtures. When using the rails generate
+ command, template test files will be generated for you and placed in this
+ directory.
+
+vendor
+ External libraries that the application depends on. Also includes the plugins
+ subdirectory. If the app has frozen rails, those gems also go here, under
+ vendor/rails/. This directory is in the load path.
diff --git a/ch09/ch10/demo/Rakefile b/ch09/ch10/demo/Rakefile
new file mode 100644
index 0000000..d958224
--- /dev/null
+++ b/ch09/ch10/demo/Rakefile
@@ -0,0 +1,7 @@
+#!/usr/bin/env rake
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Demo::Application.load_tasks
diff --git a/ch09/ch10/demo/app/assets/images/rails.png b/ch09/ch10/demo/app/assets/images/rails.png
new file mode 100644
index 0000000..d5edc04
Binary files /dev/null and b/ch09/ch10/demo/app/assets/images/rails.png differ
diff --git a/ch09/ch10/demo/app/assets/javascripts/admins.js.coffee b/ch09/ch10/demo/app/assets/javascripts/admins.js.coffee
new file mode 100644
index 0000000..7615679
--- /dev/null
+++ b/ch09/ch10/demo/app/assets/javascripts/admins.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/ch09/ch10/demo/app/assets/javascripts/application.js b/ch09/ch10/demo/app/assets/javascripts/application.js
new file mode 100644
index 0000000..9097d83
--- /dev/null
+++ b/ch09/ch10/demo/app/assets/javascripts/application.js
@@ -0,0 +1,15 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// the compiled file.
+//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
+//= require jquery
+//= require jquery_ujs
+//= require_tree .
diff --git a/ch09/ch10/demo/app/assets/javascripts/standards.js.coffee b/ch09/ch10/demo/app/assets/javascripts/standards.js.coffee
new file mode 100644
index 0000000..7615679
--- /dev/null
+++ b/ch09/ch10/demo/app/assets/javascripts/standards.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/ch09/ch10/demo/app/assets/stylesheets/admins.css.scss b/ch09/ch10/demo/app/assets/stylesheets/admins.css.scss
new file mode 100644
index 0000000..984fabc
--- /dev/null
+++ b/ch09/ch10/demo/app/assets/stylesheets/admins.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the admins controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/ch09/ch10/demo/app/assets/stylesheets/application.css b/ch09/ch10/demo/app/assets/stylesheets/application.css
new file mode 100644
index 0000000..3192ec8
--- /dev/null
+++ b/ch09/ch10/demo/app/assets/stylesheets/application.css
@@ -0,0 +1,13 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require_tree .
+ */
diff --git a/ch09/ch10/demo/app/assets/stylesheets/standards.css.scss b/ch09/ch10/demo/app/assets/stylesheets/standards.css.scss
new file mode 100644
index 0000000..1a3b62f
--- /dev/null
+++ b/ch09/ch10/demo/app/assets/stylesheets/standards.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the standards controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/ch09/ch10/demo/app/controllers/admins_controller.rb b/ch09/ch10/demo/app/controllers/admins_controller.rb
new file mode 100644
index 0000000..63872d4
--- /dev/null
+++ b/ch09/ch10/demo/app/controllers/admins_controller.rb
@@ -0,0 +1,5 @@
+class AdminsController < ApplicationController
+ def secured
+ render :text => "This is top secret code"
+ end
+end
diff --git a/ch09/ch10/demo/app/controllers/application_controller.rb b/ch09/ch10/demo/app/controllers/application_controller.rb
new file mode 100644
index 0000000..e8065d9
--- /dev/null
+++ b/ch09/ch10/demo/app/controllers/application_controller.rb
@@ -0,0 +1,3 @@
+class ApplicationController < ActionController::Base
+ protect_from_forgery
+end
diff --git a/ch09/ch10/demo/app/controllers/standards_controller.rb b/ch09/ch10/demo/app/controllers/standards_controller.rb
new file mode 100644
index 0000000..f5b0aa7
--- /dev/null
+++ b/ch09/ch10/demo/app/controllers/standards_controller.rb
@@ -0,0 +1,5 @@
+class StandardsController < ApplicationController
+ def unsecured
+ render :text => "Anybody can read this meaningless message"
+ end
+end
diff --git a/ch09/ch10/demo/app/helpers/admins_helper.rb b/ch09/ch10/demo/app/helpers/admins_helper.rb
new file mode 100644
index 0000000..d4f7b34
--- /dev/null
+++ b/ch09/ch10/demo/app/helpers/admins_helper.rb
@@ -0,0 +1,2 @@
+module AdminsHelper
+end
diff --git a/ch09/ch10/demo/app/helpers/application_helper.rb b/ch09/ch10/demo/app/helpers/application_helper.rb
new file mode 100644
index 0000000..de6be79
--- /dev/null
+++ b/ch09/ch10/demo/app/helpers/application_helper.rb
@@ -0,0 +1,2 @@
+module ApplicationHelper
+end
diff --git a/ch09/ch10/demo/app/helpers/standards_helper.rb b/ch09/ch10/demo/app/helpers/standards_helper.rb
new file mode 100644
index 0000000..c93b174
--- /dev/null
+++ b/ch09/ch10/demo/app/helpers/standards_helper.rb
@@ -0,0 +1,2 @@
+module StandardsHelper
+end
diff --git a/ch09/ch10/demo/app/mailers/.gitkeep b/ch09/ch10/demo/app/mailers/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/app/models/.gitkeep b/ch09/ch10/demo/app/models/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/app/views/layouts/application.html.erb b/ch09/ch10/demo/app/views/layouts/application.html.erb
new file mode 100644
index 0000000..0c9ec94
--- /dev/null
+++ b/ch09/ch10/demo/app/views/layouts/application.html.erb
@@ -0,0 +1,14 @@
+
+
+
+ Demo
+ <%= stylesheet_link_tag "application", :media => "all" %>
+ <%= javascript_include_tag "application" %>
+ <%= csrf_meta_tags %>
+
+
+
+<%= yield %>
+
+
+
diff --git a/ch09/ch10/demo/applicationContext-security.xml b/ch09/ch10/demo/applicationContext-security.xml
new file mode 100644
index 0000000..b237dea
--- /dev/null
+++ b/ch09/ch10/demo/applicationContext-security.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch09/ch10/demo/config.ru b/ch09/ch10/demo/config.ru
new file mode 100644
index 0000000..7e6e8c0
--- /dev/null
+++ b/ch09/ch10/demo/config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+run Demo::Application
diff --git a/ch09/ch10/demo/config/application.rb b/ch09/ch10/demo/config/application.rb
new file mode 100644
index 0000000..6d08cd3
--- /dev/null
+++ b/ch09/ch10/demo/config/application.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../boot', __FILE__)
+
+require 'rails/all'
+
+if defined?(Bundler)
+ # If you precompile assets before deploying to production, use this line
+ Bundler.require(*Rails.groups(:assets => %w(development test)))
+ # If you want your assets lazily compiled in production, use this line
+ # Bundler.require(:default, :assets, Rails.env)
+end
+
+module Demo
+ class Application < Rails::Application
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+
+ # Custom directories with classes and modules you want to be autoloadable.
+ # config.autoload_paths += %W(#{config.root}/extras)
+
+ # Only load the plugins named here, in the order given (default is alphabetical).
+ # :all can be used as a placeholder for all plugins not explicitly named.
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+ # Activate observers that should always be running.
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
+
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+ # config.time_zone = 'Central Time (US & Canada)'
+
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+ # config.i18n.default_locale = :de
+
+ # Configure the default encoding used in templates for Ruby 1.9.
+ config.encoding = "utf-8"
+
+ # Configure sensitive parameters which will be filtered from the log file.
+ config.filter_parameters += [:password]
+
+ # Enable escaping HTML in JSON.
+ config.active_support.escape_html_entities_in_json = true
+
+ # Use SQL instead of Active Record's schema dumper when creating the database.
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
+ # like if you have constraints or database-specific column types
+ # config.active_record.schema_format = :sql
+
+ # Enforce whitelist mode for mass assignment.
+ # This will create an empty whitelist of attributes available for mass-assignment for all models
+ # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
+ # parameters by using an attr_accessible or attr_protected declaration.
+ config.active_record.whitelist_attributes = true
+
+ # Enable the asset pipeline
+ config.assets.enabled = true
+
+ # Version of your assets, change this if you want to expire all your assets
+ config.assets.version = '1.0'
+ end
+end
diff --git a/ch09/ch10/demo/config/boot.rb b/ch09/ch10/demo/config/boot.rb
new file mode 100644
index 0000000..4489e58
--- /dev/null
+++ b/ch09/ch10/demo/config/boot.rb
@@ -0,0 +1,6 @@
+require 'rubygems'
+
+# Set up gems listed in the Gemfile.
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
diff --git a/ch09/ch10/demo/config/database.yml b/ch09/ch10/demo/config/database.yml
new file mode 100644
index 0000000..175f3eb
--- /dev/null
+++ b/ch09/ch10/demo/config/database.yml
@@ -0,0 +1,20 @@
+# SQLite version 3.x
+# gem 'activerecord-jdbcsqlite3-adapter'
+#
+# Configure Using Gemfile
+# gem 'activerecord-jdbcsqlite3-adapter'
+#
+development:
+ adapter: sqlite3
+ database: db/development.sqlite3
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: sqlite3
+ database: db/test.sqlite3
+
+production:
+ adapter: sqlite3
+ database: db/production.sqlite3
diff --git a/ch09/ch10/demo/config/environment.rb b/ch09/ch10/demo/config/environment.rb
new file mode 100644
index 0000000..b23fc85
--- /dev/null
+++ b/ch09/ch10/demo/config/environment.rb
@@ -0,0 +1,5 @@
+# Load the rails application
+require File.expand_path('../application', __FILE__)
+
+# Initialize the rails application
+Demo::Application.initialize!
diff --git a/ch09/ch10/demo/config/environments/development.rb b/ch09/ch10/demo/config/environments/development.rb
new file mode 100644
index 0000000..f6783a2
--- /dev/null
+++ b/ch09/ch10/demo/config/environments/development.rb
@@ -0,0 +1,37 @@
+Demo::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Log error messages when you accidentally call methods on nil.
+ config.whiny_nils = true
+
+ # Show full error reports and disable caching
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Don't care if the mailer can't send
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger
+ config.active_support.deprecation = :log
+
+ # Only use best-standards-support built into browsers
+ config.action_dispatch.best_standards_support = :builtin
+
+ # Raise exception on mass assignment protection for Active Record models
+ config.active_record.mass_assignment_sanitizer = :strict
+
+ # Log the query plan for queries taking more than this (works
+ # with SQLite, MySQL, and PostgreSQL)
+ config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+ # Do not compress assets
+ config.assets.compress = false
+
+ # Expands the lines which load the assets
+ config.assets.debug = true
+end
diff --git a/ch09/ch10/demo/config/environments/production.rb b/ch09/ch10/demo/config/environments/production.rb
new file mode 100644
index 0000000..ddcd089
--- /dev/null
+++ b/ch09/ch10/demo/config/environments/production.rb
@@ -0,0 +1,67 @@
+Demo::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # Code is not reloaded between requests
+ config.cache_classes = true
+
+ # Full error reports are disabled and caching is turned on
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Disable Rails's static asset server (Apache or nginx will already do this)
+ config.serve_static_assets = false
+
+ # Compress JavaScripts and CSS
+ config.assets.compress = true
+
+ # Don't fallback to assets pipeline if a precompiled asset is missed
+ config.assets.compile = false
+
+ # Generate digests for assets URLs
+ config.assets.digest = true
+
+ # Defaults to nil and saved in location specified by config.assets.prefix
+ # config.assets.manifest = YOUR_PATH
+
+ # Specifies the header that your server uses for sending files
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # See everything in the log (default is :info)
+ # config.log_level = :debug
+
+ # Prepend all log lines with the following tags
+ # config.log_tags = [ :subdomain, :uuid ]
+
+ # Use a different logger for distributed setups
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+ # Use a different cache store in production
+ # config.cache_store = :mem_cache_store
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server
+ # config.action_controller.asset_host = "http://assets.example.com"
+
+ # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
+ # config.assets.precompile += %w( search.js )
+
+ # Disable delivery errors, bad email addresses will be ignored
+ # config.action_mailer.raise_delivery_errors = false
+
+ # Enable threaded mode
+ # config.threadsafe!
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation can not be found)
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners
+ config.active_support.deprecation = :notify
+
+ # Log the query plan for queries taking more than this (works
+ # with SQLite, MySQL, and PostgreSQL)
+ # config.active_record.auto_explain_threshold_in_seconds = 0.5
+end
diff --git a/ch09/ch10/demo/config/environments/test.rb b/ch09/ch10/demo/config/environments/test.rb
new file mode 100644
index 0000000..1ec74da
--- /dev/null
+++ b/ch09/ch10/demo/config/environments/test.rb
@@ -0,0 +1,37 @@
+Demo::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # The test environment is used exclusively to run your application's
+ # test suite. You never need to work with it otherwise. Remember that
+ # your test database is "scratch space" for the test suite and is wiped
+ # and recreated between test runs. Don't rely on the data there!
+ config.cache_classes = true
+
+ # Configure static asset server for tests with Cache-Control for performance
+ config.serve_static_assets = true
+ config.static_cache_control = "public, max-age=3600"
+
+ # Log error messages when you accidentally call methods on nil
+ config.whiny_nils = true
+
+ # Show full error reports and disable caching
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Raise exceptions instead of rendering exception templates
+ config.action_dispatch.show_exceptions = false
+
+ # Disable request forgery protection in test environment
+ config.action_controller.allow_forgery_protection = false
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
+
+ # Raise exception on mass assignment protection for Active Record models
+ config.active_record.mass_assignment_sanitizer = :strict
+
+ # Print deprecation notices to the stderr
+ config.active_support.deprecation = :stderr
+end
diff --git a/ch09/ch10/demo/config/initializers/backtrace_silencers.rb b/ch09/ch10/demo/config/initializers/backtrace_silencers.rb
new file mode 100644
index 0000000..59385cd
--- /dev/null
+++ b/ch09/ch10/demo/config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
diff --git a/ch09/ch10/demo/config/initializers/inflections.rb b/ch09/ch10/demo/config/initializers/inflections.rb
new file mode 100644
index 0000000..5d8d9be
--- /dev/null
+++ b/ch09/ch10/demo/config/initializers/inflections.rb
@@ -0,0 +1,15 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format
+# (all these examples are active by default):
+# ActiveSupport::Inflector.inflections do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+#
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections do |inflect|
+# inflect.acronym 'RESTful'
+# end
diff --git a/ch09/ch10/demo/config/initializers/mime_types.rb b/ch09/ch10/demo/config/initializers/mime_types.rb
new file mode 100644
index 0000000..72aca7e
--- /dev/null
+++ b/ch09/ch10/demo/config/initializers/mime_types.rb
@@ -0,0 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
+# Mime::Type.register_alias "text/html", :iphone
diff --git a/ch09/ch10/demo/config/initializers/secret_token.rb b/ch09/ch10/demo/config/initializers/secret_token.rb
new file mode 100644
index 0000000..0082a23
--- /dev/null
+++ b/ch09/ch10/demo/config/initializers/secret_token.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+Demo::Application.config.secret_token = '8578af0357e8b528b8c7b057806ac3a4b091d6f5faf465d197074e48eff818e72118681ebfc5fc521cb76233473e1c1e372fe08db01cc7404e9558765001f262'
diff --git a/ch09/ch10/demo/config/initializers/session_store.rb b/ch09/ch10/demo/config/initializers/session_store.rb
new file mode 100644
index 0000000..52ee4cb
--- /dev/null
+++ b/ch09/ch10/demo/config/initializers/session_store.rb
@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+Demo::Application.config.session_store :cookie_store, key: '_demo_session'
+
+# Use the database for sessions instead of the cookie-based default,
+# which shouldn't be used to store highly confidential information
+# (create the session table with "rails generate session_migration")
+# Demo::Application.config.session_store :active_record_store
diff --git a/ch09/ch10/demo/config/initializers/wrap_parameters.rb b/ch09/ch10/demo/config/initializers/wrap_parameters.rb
new file mode 100644
index 0000000..999df20
--- /dev/null
+++ b/ch09/ch10/demo/config/initializers/wrap_parameters.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+#
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters format: [:json]
+end
+
+# Disable root element in JSON by default.
+ActiveSupport.on_load(:active_record) do
+ self.include_root_in_json = false
+end
diff --git a/ch09/ch10/demo/config/locales/en.yml b/ch09/ch10/demo/config/locales/en.yml
new file mode 100644
index 0000000..179c14c
--- /dev/null
+++ b/ch09/ch10/demo/config/locales/en.yml
@@ -0,0 +1,5 @@
+# Sample localization file for English. Add more files in this directory for other locales.
+# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
+
+en:
+ hello: "Hello world"
diff --git a/ch09/ch10/demo/config/routes.rb b/ch09/ch10/demo/config/routes.rb
new file mode 100644
index 0000000..7fab23e
--- /dev/null
+++ b/ch09/ch10/demo/config/routes.rb
@@ -0,0 +1,60 @@
+Demo::Application.routes.draw do
+ # The priority is based upon order of creation:
+ # first created -> highest priority.
+
+ # Sample of regular route:
+ # match 'products/:id' => 'catalog#view'
+ # Keep in mind you can assign values other than :controller and :action
+
+ # Sample of named route:
+ # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
+ # This route can be invoked with purchase_url(:id => product.id)
+
+ # Sample resource route (maps HTTP verbs to controller actions automatically):
+ # resources :products
+
+ # Sample resource route with options:
+ # resources :products do
+ # member do
+ # get 'short'
+ # post 'toggle'
+ # end
+ #
+ # collection do
+ # get 'sold'
+ # end
+ # end
+
+ # Sample resource route with sub-resources:
+ # resources :products do
+ # resources :comments, :sales
+ # resource :seller
+ # end
+
+ # Sample resource route with more complex sub-resources
+ # resources :products do
+ # resources :comments
+ # resources :sales do
+ # get 'recent', :on => :collection
+ # end
+ # end
+
+ # Sample resource route within a namespace:
+ # namespace :admin do
+ # # Directs /admin/products/* to Admin::ProductsController
+ # # (app/controllers/admin/products_controller.rb)
+ # resources :products
+ # end
+
+ # You can have the root of your site routed with "root"
+ # just remember to delete public/index.html.
+ # root :to => 'welcome#index'
+
+ # See how all your routes lay out with "rake routes"
+
+ # This is a legacy wild controller route that's not recommended for RESTful applications.
+ # Note: This route will make all actions in every controller accessible via GET requests.
+ # match ':controller(/:action(/:id))(.:format)'
+ match 'admin/message' => 'admins#secured'
+ match 'standard/message' => 'standards#unsecured'
+end
diff --git a/ch09/ch10/demo/config/warble.rb b/ch09/ch10/demo/config/warble.rb
new file mode 100644
index 0000000..e11d67b
--- /dev/null
+++ b/ch09/ch10/demo/config/warble.rb
@@ -0,0 +1,151 @@
+# Disable Rake-environment-task framework detection by uncommenting/setting to false
+# Warbler.framework_detection = false
+
+# Warbler web application assembly configuration file
+Warbler::Config.new do |config|
+ # Features: additional options controlling how the jar is built.
+ # Currently the following features are supported:
+ # - gemjar: package the gem repository in a jar file in WEB-INF/lib
+ # - executable: embed a web server and make the war executable
+ # - compiled: compile .rb files to .class files
+ # config.features = %w(gemjar)
+
+ # Application directories to be included in the webapp.
+ config.dirs = %w(app config lib log vendor tmp)
+
+ # Additional files/directories to include, above those in config.dirs
+ config.includes = FileList["db"]
+
+ # Additional files/directories to exclude
+ # config.excludes = FileList["lib/tasks/*"]
+
+ # Additional Java .jar files to include. Note that if .jar files are placed
+ # in lib (and not otherwise excluded) then they need not be mentioned here.
+ # JRuby and JRuby-Rack are pre-loaded in this list. Be sure to include your
+ # own versions if you directly set the value
+ # config.java_libs += FileList["lib/java/*.jar"]
+
+ # Loose Java classes and miscellaneous files to be included.
+ # config.java_classes = FileList["target/classes/**.*"]
+
+ # One or more pathmaps defining how the java classes should be copied into
+ # the archive. The example pathmap below accompanies the java_classes
+ # configuration above. See http://rake.rubyforge.org/classes/String.html#M000017
+ # for details of how to specify a pathmap.
+ # config.pathmaps.java_classes << "%{target/classes/,}p"
+
+ # Bundler support is built-in. If Warbler finds a Gemfile in the
+ # project directory, it will be used to collect the gems to bundle
+ # in your application. If you wish to explicitly disable this
+ # functionality, uncomment here.
+ # config.bundler = false
+
+ # An array of Bundler groups to avoid including in the war file.
+ # Defaults to ["development", "test"].
+ # config.bundle_without = []
+
+ # Other gems to be included. If you don't use Bundler or a gemspec
+ # file, you need to tell Warbler which gems your application needs
+ # so that they can be packaged in the archive.
+ # For Rails applications, the Rails gems are included by default
+ # unless the vendor/rails directory is present.
+ # config.gems += ["activerecord-jdbcmysql-adapter", "jruby-openssl"]
+ # config.gems << "tzinfo"
+
+ # Uncomment this if you don't want to package rails gem.
+ # config.gems -= ["rails"]
+
+ # The most recent versions of gems are used.
+ # You can specify versions of gems by using a hash assignment:
+ # config.gems["rails"] = "2.3.10"
+
+ # You can also use regexps or Gem::Dependency objects for flexibility or
+ # finer-grained control.
+ # config.gems << /^merb-/
+ # config.gems << Gem::Dependency.new("merb-core", "= 0.9.3")
+
+ # Include gem dependencies not mentioned specifically. Default is
+ # true, uncomment to turn off.
+ # config.gem_dependencies = false
+
+ # Array of regular expressions matching relative paths in gems to be
+ # excluded from the war. Defaults to empty, but you can set it like
+ # below, which excludes test files.
+ # config.gem_excludes = [/^(test|spec)\//]
+
+ # Pathmaps for controlling how application files are copied into the archive
+ # config.pathmaps.application = ["WEB-INF/%p"]
+
+ # Name of the archive (without the extension). Defaults to the basename
+ # of the project directory.
+ # config.jar_name = "mywar"
+
+ # Name of the MANIFEST.MF template for the war file. Defaults to a simple
+ # MANIFEST.MF that contains the version of Warbler used to create the war file.
+ # config.manifest_file = "config/MANIFEST.MF"
+
+ # When using the 'compiled' feature and specified, only these Ruby
+ # files will be compiled. Default is to compile all \.rb files in
+ # the application.
+ # config.compiled_ruby_files = FileList['app/**/*.rb']
+
+ # === War files only below here ===
+
+ # Path to the pre-bundled gem directory inside the war file. Default
+ # is 'WEB-INF/gems'. Specify path if gems are already bundled
+ # before running Warbler. This also sets 'gem.path' inside web.xml.
+ # config.gem_path = "WEB-INF/vendor/bundler_gems"
+
+ # Files for WEB-INF directory (next to web.xml). This contains
+ # web.xml by default. If there is an .erb-File it will be processed
+ # with webxml-config. You may want to exclude this file via
+ # config.excludes.
+ config.webinf_files += FileList["applicationContext-security.xml"]
+
+ # Files to be included in the root of the webapp. Note that files in public
+ # will have the leading 'public/' part of the path stripped during staging.
+ # config.public_html = FileList["public/**/*", "doc/**/*"]
+
+ # Pathmaps for controlling how public HTML files are copied into the .war
+ # config.pathmaps.public_html = ["%{public/,}p"]
+
+ # Embedded webserver to use with the 'executable' feature. Currently supported
+ # webservers are:
+ # * winstone (default) - Winstone 0.9.10 from sourceforge
+ # * jenkins-ci.winstone - Improved Winstone from Jenkins CI
+ # * jetty - Embedded Jetty from Eclipse
+ # config.webserver = 'jetty'
+
+ # Value of RAILS_ENV for the webapp -- default as shown below
+ # config.webxml.rails.env = ENV['RAILS_ENV'] || 'production'
+
+ # Application booter to use, one of :rack, :rails, or :merb (autodetected by default)
+ # config.webxml.booter = :rails
+
+ # Set JRuby to run in 1.9 mode.
+ config.webxml.jruby.compat.version = "1.9"
+
+ # When using the :rack booter, "Rackup" script to use.
+ # - For 'rackup.path', the value points to the location of the rackup
+ # script in the web archive file. You need to make sure this file
+ # gets included in the war, possibly by adding it to config.includes
+ # or config.webinf_files above.
+ # - For 'rackup', the rackup script you provide as an inline string
+ # is simply embedded in web.xml.
+ # The script is evaluated in a Rack::Builder to load the application.
+ # Examples:
+ # config.webxml.rackup.path = 'WEB-INF/hello.ru'
+ # config.webxml.rackup = %{require './lib/demo'; run Rack::Adapter::Camping.new(Demo)}
+ # config.webxml.rackup = require 'cgi' && CGI::escapeHTML(File.read("config.ru"))
+
+ # Control the pool of Rails runtimes. Leaving unspecified means
+ # the pool will grow as needed to service requests. It is recommended
+ # that you fix these values when running a production server!
+ # If you're using threadsafe! mode, you probably don't want to set these values,
+ # since 1 runtime(default for threadsafe mode) will be enough.
+ # config.webxml.jruby.min.runtimes = 2
+ # config.webxml.jruby.max.runtimes = 4
+
+ # JNDI data source name
+ # config.webxml.jndi = 'jdbc/rails'
+end
diff --git a/ch09/ch10/demo/config/web.xml.erb b/ch09/ch10/demo/config/web.xml.erb
new file mode 100644
index 0000000..319022f
--- /dev/null
+++ b/ch09/ch10/demo/config/web.xml.erb
@@ -0,0 +1,57 @@
+
+
+<% webxml.context_params.each do |k,v| %>
+
+ <%= k %>
+ <%= v %>
+
+<% end %>
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ <%= webxml.servlet_context_listener %>
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+
+ RackFilter
+ org.jruby.rack.RackFilter
+
+
+
+ springSecurityFilterChain
+ /*
+
+
+
+ RackFilter
+ /*
+
+
+<% if webxml.jndi then [webxml.jndi].flatten.each do |jndi| %>
+
+ <%= jndi %>
+ javax.sql.DataSource
+ Container
+
+<% end; end %>
+
diff --git a/ch09/ch10/demo/db/seeds.rb b/ch09/ch10/demo/db/seeds.rb
new file mode 100644
index 0000000..4edb1e8
--- /dev/null
+++ b/ch09/ch10/demo/db/seeds.rb
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+#
+# Examples:
+#
+# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
+# Mayor.create(name: 'Emanuel', city: cities.first)
diff --git a/ch09/ch10/demo/doc/README_FOR_APP b/ch09/ch10/demo/doc/README_FOR_APP
new file mode 100644
index 0000000..fe41f5c
--- /dev/null
+++ b/ch09/ch10/demo/doc/README_FOR_APP
@@ -0,0 +1,2 @@
+Use this README file to introduce your application and point to useful places in the API for learning more.
+Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
diff --git a/ch09/ch10/demo/lib/aopalliance-1.0.jar b/ch09/ch10/demo/lib/aopalliance-1.0.jar
new file mode 100644
index 0000000..578b1a0
Binary files /dev/null and b/ch09/ch10/demo/lib/aopalliance-1.0.jar differ
diff --git a/ch09/ch10/demo/lib/assets/.gitkeep b/ch09/ch10/demo/lib/assets/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/lib/commons-codec-1.3.jar b/ch09/ch10/demo/lib/commons-codec-1.3.jar
new file mode 100644
index 0000000..957b675
Binary files /dev/null and b/ch09/ch10/demo/lib/commons-codec-1.3.jar differ
diff --git a/ch09/ch10/demo/lib/commons-logging-1.1.1.jar b/ch09/ch10/demo/lib/commons-logging-1.1.1.jar
new file mode 100644
index 0000000..1deef14
Binary files /dev/null and b/ch09/ch10/demo/lib/commons-logging-1.1.1.jar differ
diff --git a/ch09/ch10/demo/lib/javax.servlet-api-3.0.1.jar b/ch09/ch10/demo/lib/javax.servlet-api-3.0.1.jar
new file mode 100644
index 0000000..4e2edcc
Binary files /dev/null and b/ch09/ch10/demo/lib/javax.servlet-api-3.0.1.jar differ
diff --git a/ch09/ch10/demo/lib/spring-aop-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-aop-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..37206d3
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-aop-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-asm-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-asm-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..be6a913
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-asm-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-beans-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-beans-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..c4bc850
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-beans-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-context-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-context-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..57f7570
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-context-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-core-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-core-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..e896e27
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-core-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-expression-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-expression-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..4064858
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-expression-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-jdbc-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-jdbc-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..28a5aaa
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-jdbc-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-security-config-3.1.0.RELEASE.jar b/ch09/ch10/demo/lib/spring-security-config-3.1.0.RELEASE.jar
new file mode 100644
index 0000000..d405e58
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-security-config-3.1.0.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-security-core-3.1.0.RELEASE.jar b/ch09/ch10/demo/lib/spring-security-core-3.1.0.RELEASE.jar
new file mode 100644
index 0000000..8f63bcd
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-security-core-3.1.0.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-security-crypto-3.1.0.RELEASE.jar b/ch09/ch10/demo/lib/spring-security-crypto-3.1.0.RELEASE.jar
new file mode 100644
index 0000000..9a6179d
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-security-crypto-3.1.0.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-security-web-3.1.0.RELEASE.jar b/ch09/ch10/demo/lib/spring-security-web-3.1.0.RELEASE.jar
new file mode 100644
index 0000000..fd5f4b2
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-security-web-3.1.0.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-tx-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-tx-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..262eb8d
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-tx-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/spring-web-3.0.6.RELEASE.jar b/ch09/ch10/demo/lib/spring-web-3.0.6.RELEASE.jar
new file mode 100644
index 0000000..761578b
Binary files /dev/null and b/ch09/ch10/demo/lib/spring-web-3.0.6.RELEASE.jar differ
diff --git a/ch09/ch10/demo/lib/tasks/.gitkeep b/ch09/ch10/demo/lib/tasks/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/log/.gitkeep b/ch09/ch10/demo/log/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/public/404.html b/ch09/ch10/demo/public/404.html
new file mode 100644
index 0000000..9a48320
--- /dev/null
+++ b/ch09/ch10/demo/public/404.html
@@ -0,0 +1,26 @@
+
+
+
+ The page you were looking for doesn't exist (404)
+
+
+
+
+
+
+
The page you were looking for doesn't exist.
+
You may have mistyped the address or the page may have moved.
+
+
+
diff --git a/ch09/ch10/demo/public/422.html b/ch09/ch10/demo/public/422.html
new file mode 100644
index 0000000..83660ab
--- /dev/null
+++ b/ch09/ch10/demo/public/422.html
@@ -0,0 +1,26 @@
+
+
+
+ The change you wanted was rejected (422)
+
+
+
+
+
+
+
The change you wanted was rejected.
+
Maybe you tried to change something you didn't have access to.
+
+
+
diff --git a/ch09/ch10/demo/public/500.html b/ch09/ch10/demo/public/500.html
new file mode 100644
index 0000000..f3648a0
--- /dev/null
+++ b/ch09/ch10/demo/public/500.html
@@ -0,0 +1,25 @@
+
+
+
+ We're sorry, but something went wrong (500)
+
+
+
+
+
+
+
We're sorry, but something went wrong.
+
+
+
diff --git a/ch09/ch10/demo/public/favicon.ico b/ch09/ch10/demo/public/favicon.ico
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/public/index.html b/ch09/ch10/demo/public/index.html
new file mode 100644
index 0000000..a1d5099
--- /dev/null
+++ b/ch09/ch10/demo/public/index.html
@@ -0,0 +1,241 @@
+
+
+
+ Ruby on Rails: Welcome aboard
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Getting started
+
Here’s how to get rolling:
+
+
+
+ Use rails generate
to create your models and controllers
+ To see all available options, run it without parameters.
+
+
+
+ Set up a default route and remove public/index.html
+ Routes are set up in config/routes.rb .
+
+
+
+ Create your database
+ Run rake db:create
to create your database. If you're not using SQLite (the default), edit config/database.yml with your username and password.
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/demo/public/robots.txt b/ch09/ch10/demo/public/robots.txt
new file mode 100644
index 0000000..085187f
--- /dev/null
+++ b/ch09/ch10/demo/public/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-Agent: *
+# Disallow: /
diff --git a/ch09/ch10/demo/script/rails b/ch09/ch10/demo/script/rails
new file mode 100644
index 0000000..f8da2cf
--- /dev/null
+++ b/ch09/ch10/demo/script/rails
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
+
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require File.expand_path('../../config/boot', __FILE__)
+require 'rails/commands'
diff --git a/ch09/ch10/demo/test/fixtures/.gitkeep b/ch09/ch10/demo/test/fixtures/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/test/functional/.gitkeep b/ch09/ch10/demo/test/functional/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/test/functional/admins_controller_test.rb b/ch09/ch10/demo/test/functional/admins_controller_test.rb
new file mode 100644
index 0000000..3168556
--- /dev/null
+++ b/ch09/ch10/demo/test/functional/admins_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class AdminsControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/ch09/ch10/demo/test/functional/standards_controller_test.rb b/ch09/ch10/demo/test/functional/standards_controller_test.rb
new file mode 100644
index 0000000..f15cdfd
--- /dev/null
+++ b/ch09/ch10/demo/test/functional/standards_controller_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class StandardsControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/ch09/ch10/demo/test/integration/.gitkeep b/ch09/ch10/demo/test/integration/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/test/performance/browsing_test.rb b/ch09/ch10/demo/test/performance/browsing_test.rb
new file mode 100644
index 0000000..3fea27b
--- /dev/null
+++ b/ch09/ch10/demo/test/performance/browsing_test.rb
@@ -0,0 +1,12 @@
+require 'test_helper'
+require 'rails/performance_test_help'
+
+class BrowsingTest < ActionDispatch::PerformanceTest
+ # Refer to the documentation for all available options
+ # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory]
+ # :output => 'tmp/performance', :formats => [:flat] }
+
+ def test_homepage
+ get '/'
+ end
+end
diff --git a/ch09/ch10/demo/test/test_helper.rb b/ch09/ch10/demo/test/test_helper.rb
new file mode 100644
index 0000000..8bf1192
--- /dev/null
+++ b/ch09/ch10/demo/test/test_helper.rb
@@ -0,0 +1,13 @@
+ENV["RAILS_ENV"] = "test"
+require File.expand_path('../../config/environment', __FILE__)
+require 'rails/test_help'
+
+class ActiveSupport::TestCase
+ # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
+ #
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
+ # -- they do not yet inherit this setting
+ fixtures :all
+
+ # Add more helper methods to be used by all tests here...
+end
diff --git a/ch09/ch10/demo/test/unit/.gitkeep b/ch09/ch10/demo/test/unit/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/test/unit/helpers/admins_helper_test.rb b/ch09/ch10/demo/test/unit/helpers/admins_helper_test.rb
new file mode 100644
index 0000000..fb7d533
--- /dev/null
+++ b/ch09/ch10/demo/test/unit/helpers/admins_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class AdminsHelperTest < ActionView::TestCase
+end
diff --git a/ch09/ch10/demo/test/unit/helpers/standards_helper_test.rb b/ch09/ch10/demo/test/unit/helpers/standards_helper_test.rb
new file mode 100644
index 0000000..227d020
--- /dev/null
+++ b/ch09/ch10/demo/test/unit/helpers/standards_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class StandardsHelperTest < ActionView::TestCase
+end
diff --git a/ch09/ch10/demo/vendor/assets/javascripts/.gitkeep b/ch09/ch10/demo/vendor/assets/javascripts/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/vendor/assets/stylesheets/.gitkeep b/ch09/ch10/demo/vendor/assets/stylesheets/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/demo/vendor/plugins/.gitkeep b/ch09/ch10/demo/vendor/plugins/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ch09/ch10/scala-example/.classpath b/ch09/ch10/scala-example/.classpath
new file mode 100644
index 0000000..55910cd
--- /dev/null
+++ b/ch09/ch10/scala-example/.classpath
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/scala-example/.project b/ch09/ch10/scala-example/.project
new file mode 100644
index 0000000..d15c097
--- /dev/null
+++ b/ch09/ch10/scala-example/.project
@@ -0,0 +1,42 @@
+
+
+ scala-example
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch09/ch10/scala-example/.settings/.jsdtscope b/ch09/ch10/scala-example/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch09/ch10/scala-example/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/scala-example/.settings/org.eclipse.jdt.core.prefs b/ch09/ch10/scala-example/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch09/ch10/scala-example/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch09/ch10/scala-example/.settings/org.eclipse.m2e.core.prefs b/ch09/ch10/scala-example/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch09/ch10/scala-example/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch09/ch10/scala-example/.settings/org.eclipse.wst.common.component b/ch09/ch10/scala-example/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..9a26fad
--- /dev/null
+++ b/ch09/ch10/scala-example/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/scala-example/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch09/ch10/scala-example/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d74c55e
--- /dev/null
+++ b/ch09/ch10/scala-example/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch09/ch10/scala-example/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch09/ch10/scala-example/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch09/ch10/scala-example/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch09/ch10/scala-example/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch09/ch10/scala-example/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch09/ch10/scala-example/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch09/ch10/scala-example/pom.xml b/ch09/ch10/scala-example/pom.xml
new file mode 100644
index 0000000..69c062e
--- /dev/null
+++ b/ch09/ch10/scala-example/pom.xml
@@ -0,0 +1,118 @@
+
+ 4.0.0
+ com.apress.pss
+ scala-example
+ war
+ 1.0-SNAPSHOT
+ scala-example Maven Webapp
+ http://maven.apache.org
+
+
+ scala-tools.org
+ Scala-tools Maven2 Repository
+ http://scala-tools.org/repo-releases
+
+
+
+
+ scala-tools.org
+ Scala-tools Maven2 Repository
+ http://scala-tools.org/repo-releases
+
+
+
+
+ org.scala-tools
+ maven-scala-plugin
+ 2.15.2
+
+
+ org.scala-lang
+ scala-library
+ 2.9.2
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+
+ scala-example
+ src/main/scala
+ src/test/scala
+
+
+ org.scala-tools
+ maven-scala-plugin
+
+
+ scala-compile-first
+ process-resources
+
+ add-source
+ compile
+
+
+
+ scala-test-compile
+ process-test-resources
+
+ testCompile
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+
+
diff --git a/ch09/ch10/scala-example/src/main/scala/com/apress/pss/scala/service/ScalaService.scala b/ch09/ch10/scala-example/src/main/scala/com/apress/pss/scala/service/ScalaService.scala
new file mode 100644
index 0000000..8e63cf4
--- /dev/null
+++ b/ch09/ch10/scala-example/src/main/scala/com/apress/pss/scala/service/ScalaService.scala
@@ -0,0 +1,12 @@
+package com.apress.pss.scala.service;
+import org.springframework.stereotype.Service
+import org.springframework.security.access.annotation.Secured
+
+trait ScalaServiceFacade {
+ def scalaService: String
+}
+
+class ScalaService extends ScalaServiceFacade{
+ @Secured(Array("ROLE_USER"))
+ def scalaService() = "Service accessed"
+}
\ No newline at end of file
diff --git a/ch09/ch10/scala-example/src/main/scala/com/apress/pss/scala/web/ScalaController.scala b/ch09/ch10/scala-example/src/main/scala/com/apress/pss/scala/web/ScalaController.scala
new file mode 100644
index 0000000..34b4753
--- /dev/null
+++ b/ch09/ch10/scala-example/src/main/scala/com/apress/pss/scala/web/ScalaController.scala
@@ -0,0 +1,18 @@
+package com.apress.pss.scala.web;
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RequestMethod
+import org.springframework.stereotype.Controller
+import com.apress.pss.scala.service.ScalaServiceFacade
+import javax.servlet.http.HttpServletResponse
+import javax.servlet.http.HttpServletRequest
+
+@RequestMapping(Array("/enter"))
+class ScalaController(service: ScalaServiceFacade) {
+
+ @RequestMapping(value = Array("/scala"), method = Array(RequestMethod.GET))
+ def scalaRequest(request:HttpServletRequest, response:HttpServletResponse) = {
+ val value = service.scalaService
+ response.getWriter().write(value)
+ }
+}
\ No newline at end of file
diff --git a/ch09/ch10/scala-example/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch09/ch10/scala-example/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..9f9f09e
--- /dev/null
+++ b/ch09/ch10/scala-example/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/scala-example/src/main/webapp/WEB-INF/scala-servlet.xml b/ch09/ch10/scala-example/src/main/webapp/WEB-INF/scala-servlet.xml
new file mode 100644
index 0000000..86d65d3
--- /dev/null
+++ b/ch09/ch10/scala-example/src/main/webapp/WEB-INF/scala-servlet.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch09/ch10/scala-example/src/main/webapp/WEB-INF/web.xml b/ch09/ch10/scala-example/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..77d011e
--- /dev/null
+++ b/ch09/ch10/scala-example/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/applicationContext-security.xml
+
+
+
+
+ scala
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ scala
+ /
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
+
+
diff --git a/ch09/ch10/scala-example/src/main/webapp/index.jsp b/ch09/ch10/scala-example/src/main/webapp/index.jsp
new file mode 100644
index 0000000..c38169b
--- /dev/null
+++ b/ch09/ch10/scala-example/src/main/webapp/index.jsp
@@ -0,0 +1,5 @@
+
+
+Hello World!
+
+
diff --git a/ch09/ch10/struts-example/.classpath b/ch09/ch10/struts-example/.classpath
new file mode 100644
index 0000000..cbde964
--- /dev/null
+++ b/ch09/ch10/struts-example/.classpath
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/struts-example/.project b/ch09/ch10/struts-example/.project
new file mode 100644
index 0000000..c1c99c2
--- /dev/null
+++ b/ch09/ch10/struts-example/.project
@@ -0,0 +1,48 @@
+
+
+ struts-example
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch09/ch10/struts-example/.settings/.jsdtscope b/ch09/ch10/struts-example/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch09/ch10/struts-example/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/struts-example/.settings/org.eclipse.jdt.core.prefs b/ch09/ch10/struts-example/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch09/ch10/struts-example/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch09/ch10/struts-example/.settings/org.eclipse.m2e.core.prefs b/ch09/ch10/struts-example/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch09/ch10/struts-example/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch09/ch10/struts-example/.settings/org.eclipse.wst.common.component b/ch09/ch10/struts-example/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..0024c68
--- /dev/null
+++ b/ch09/ch10/struts-example/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/struts-example/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch09/ch10/struts-example/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..c09dc2d
--- /dev/null
+++ b/ch09/ch10/struts-example/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch09/ch10/struts-example/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch09/ch10/struts-example/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch09/ch10/struts-example/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch09/ch10/struts-example/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch09/ch10/struts-example/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/pom.xml b/ch09/ch10/struts-example/pom.xml
new file mode 100644
index 0000000..577748f
--- /dev/null
+++ b/ch09/ch10/struts-example/pom.xml
@@ -0,0 +1,137 @@
+
+
+
+ 4.0.0
+ com.apress.pss.struts
+ struts-example
+ 1.0-SNAPSHOT
+ war
+ struts-example
+ Struts 2 Starter
+
+
+ 2.3.7
+
+
+
+
+
+ junit
+ junit
+ 3.8.1
+ test
+
+
+
+
+ org.apache.struts
+ struts2-core
+ ${struts2.version}
+
+
+
+ org.apache.struts
+ struts2-sitemesh-plugin
+ ${struts2.version}
+
+
+
+ org.apache.struts
+ struts2-spring-plugin
+ ${struts2.version}
+
+
+
+ org.apache.struts
+ struts2-config-browser-plugin
+ ${struts2.version}
+
+
+
+
+ javax.servlet
+ servlet-api
+ 2.4
+ provided
+
+
+
+ javax.servlet
+ jsp-api
+ 2.0
+ provided
+
+
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.1.1
+
+
+
+
+ uk.ltd.getahead
+ dwr
+ 1.1-beta-3
+
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.3.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.3.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+ org.springframework
+ spring-webmvc
+ 3.0.6.RELEASE
+
+
+
+
+ struts2-archetype-starter
+
+
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+
+
+
+ org.mortbay.jetty
+ maven-jetty-plugin
+ 6.1.21
+
+ 10
+
+ src/main/webapp/WEB-INF
+ src/main/webapp/WEB-INF/web.xml
+ src/main/resources/struts.xml
+ src/main/resources/applicationContext.xml
+
+
+
+
+
+
diff --git a/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/DateConverter.java b/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/DateConverter.java
new file mode 100644
index 0000000..f398f2e
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/DateConverter.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.apress.pss.struts;
+
+import org.apache.struts2.util.StrutsTypeConverter;
+
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+import java.util.Map;
+import java.util.Date;
+import com.opensymphony.xwork2.conversion.TypeConversionException;
+
+/**
+ *
+ */
+public class DateConverter extends StrutsTypeConverter {
+ public Object convertFromString(Map context, String[] values, Class toClass) {
+ if (values != null && values.length > 0 && values[0] != null && values[0].length() > 0) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
+ try {
+ return sdf.parse(values[0]);
+ }
+ catch(ParseException e) {
+ throw new TypeConversionException(e);
+ }
+ }
+ return null;
+ }
+ public String convertToString(Map context, Object o) {
+ if (o instanceof Date) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
+ return sdf.format((Date)o);
+ }
+ return "";
+ }
+}
+
diff --git a/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/HelloWorldAction.java b/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/HelloWorldAction.java
new file mode 100644
index 0000000..269f479
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/HelloWorldAction.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.apress.pss.struts;
+
+import java.util.Date;
+
+import org.springframework.security.access.annotation.Secured;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.validator.annotations.Validation;
+import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
+import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator;
+import com.opensymphony.xwork2.conversion.annotations.Conversion;
+import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
+
+public class HelloWorldAction extends ActionSupport {
+
+ @Secured("ROLE_USER")
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/IndexAction.java b/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/IndexAction.java
new file mode 100644
index 0000000..b299beb
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/java/com/apress/pss/struts/IndexAction.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.apress.pss.struts;
+
+import com.opensymphony.xwork2.ActionSupport;
+import java.util.Date;
+import com.opensymphony.xwork2.conversion.annotations.Conversion;
+import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
+
+/**
+ *
+ */
+@Conversion()
+public class IndexAction extends ActionSupport {
+
+ private Date now = new Date(System.currentTimeMillis());
+
+ @TypeConversion(converter = "com.apress.pss.struts.DateConverter")
+ public Date getDateNow() { return now; }
+
+ public String execute() throws Exception {
+ now = new Date(System.currentTimeMillis());
+ return SUCCESS;
+ }
+}
diff --git a/ch09/ch10/struts-example/src/main/resources/applicationContext.xml b/ch09/ch10/struts-example/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000..c707fb1
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/resources/applicationContext.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/globalmessages.properties b/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/globalmessages.properties
new file mode 100644
index 0000000..00eb8e1
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/globalmessages.properties
@@ -0,0 +1,5 @@
+#
+# Here is where the global I18n messages goes
+#
+
+some.key=Some Messages
diff --git a/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/log4j.properties b/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/log4j.properties
new file mode 100644
index 0000000..cfd02d8
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/log4j.properties
@@ -0,0 +1,20 @@
+
+log4j.rootLogger = DEBUG, stdout
+
+
+log4j.category.com.opensymphony.sitemesh=DEBUG
+log4j.category.org.apache.struts2=INFO
+log4j.category.org.apache=INFO
+log4j.category.catalia=INFO
+
+
+
+
+log4j.appender.stdout = org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Threshold = DEBUG
+log4j.appender.stdout.Target = System.out
+log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern = %d{ISO8601} %-5p [%F:%L] : %m%n
+
+
+
diff --git a/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/struts.properties b/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/struts.properties
new file mode 100644
index 0000000..8366f41
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/struts.properties
@@ -0,0 +1,135 @@
+### START SNIPPET: complete_file
+
+### Struts 2.0 default properties
+###(can be overridden by a struts.properties file in the root of the classpath)
+###
+
+### Specifies the Configuration used to configure Struts 2.0
+### one could extend org.apache.struts2.config.Configuration
+### to build one's customize way of getting the configurations parameters into Struts 2.0
+# struts.configuration=org.apache.struts2.config.DefaultConfiguration
+
+### This can be used to set your default locale and encoding scheme
+# struts.locale=en_US
+struts.i18n.encoding=UTF-8
+
+### if specified, the default object factory can be overridden here
+### Note: short-hand notation is supported in some cases, such as "spring"
+### Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here
+struts.objectFactory = spring
+
+### specifies the autoWiring logic when using the SpringObjectFactory.
+### valid values are: name, type, auto, and constructor (name is the default)
+struts.objectFactory.spring.autoWire = name
+
+### indicates to the struts-action-2.0-spring integration if Class instances should be cached
+### this should, until a future Spring release makes it possible, be left as true
+### unless you know exactly what you are doing!
+### valid values are: true, false (true is the default)
+struts.objectFactory.spring.useClassCache = true
+
+### if specified, the default object type determiner can be overridden here
+### Note: short-hand notation is supported in some cases, such as "tiger" or "notiger"
+### Alternatively, you can provide a com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation name here
+### Note: if you have the xwork2-tiger.jar within your classpath, GenericsObjectTypeDeterminer is used by default
+### To disable tiger support use the "notiger" property value here.
+#struts.objectTypeDeterminer = tiger
+#struts.objectTypeDeterminer = notiger
+
+### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
+# struts.multipart.parser=cos
+# struts.multipart.parser=pell
+struts.multipart.parser=jakarta
+# uses javax.servlet.context.tempdir by default
+struts.multipart.saveDir=
+struts.multipart.maxSize=2097152
+
+### Load custom property files (does not override struts.properties!)
+# struts.custom.properties=application,com/webwork/extension/custom
+
+### How request URLs are mapped to and from actions
+struts.mapper.class=org.apache.struts2.dispatcher.mapper.DefaultActionMapper
+
+### Used by the DefaultActionMapper
+### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do
+struts.action.extension=action
+
+### Used by FilterDispatcher
+### If true then SAF serves static content from inside its jar.
+### If false then the static content must be available at /struts
+struts.serve.static=true
+
+### Used by FilterDispatcher
+### This is good for development where one wants changes to the static content be
+### fetch on each request.
+### NOTE: This will only have effect if struts.serve.static=true
+### If true -> SAF will write out header for static contents such that they will
+### be cached by web browsers (using Date, Cache-Content, Pragma, Expires)
+### headers).
+### If false -> SAF will write out header for static contents such that they are
+### NOT to be cached by web browser (using Cache-Content, Pragma, Expires
+### headers)
+struts.serve.static.browserCache=true
+
+### use alternative syntax that requires %{} in most places
+### to evaluate expressions for String attributes for tags
+struts.tag.altSyntax=true
+
+### when set to true, Struts 2.0 will act much more friendly for developers. This
+### includes:
+### - struts.i18n.reload = true
+### - struts.configuration.xml.reload = true
+### - raising various debug or ignorable problems to errors
+### For example: normally a request to foo.action?someUnknownField=true should
+### be ignored (given that any value can come from the web and it
+### should not be trusted). However, during development, it may be
+### useful to know when these errors are happening and be told of
+### them right away.
+struts.devMode = false
+
+### when set to true, resource bundles will be reloaded on _every_ request.
+### this is good during development, but should never be used in production
+struts.i18n.reload=false
+
+### Standard UI theme
+### Change this to reflect which path should be used for JSP control tag templates by default
+struts.ui.theme=xhtml
+struts.ui.templateDir=template
+#sets the default template type. Either ftl, vm, or jsp
+struts.ui.templateSuffix=ftl
+
+### Configuration reloading
+### This will cause the configuration to reload struts.xml when it is changed
+struts.configuration.xml.reload=false
+
+### Location of velocity.properties file. defaults to velocity.properties
+# struts.velocity.configfile = velocity.properties
+
+### Comma separated list of VelocityContext classnames to chain to the StrutsVelocityContext
+# struts.velocity.contexts =
+
+### used to build URLs, such as the UrlTag
+struts.url.http.port = 80
+struts.url.https.port = 443
+
+### Load custom default resource bundles
+# struts.custom.i18n.resources=testmessages,testmessages2
+struts.custom.i18n.resources=globalmessages
+
+### workaround for some app servers that don't handle HttpServletRequest.getParameterMap()
+### often used for WebLogic, Orion, and OC4J
+struts.dispatcher.parametersWorkaround = false
+
+### configure the Freemarker Manager class to be used
+### Allows user to plug-in customised Freemarker Manager if necessary
+### MUST extends off org.apache.struts2.views.freemarker.FreemarkerManager
+#struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager
+
+### See the StrutsBeanWrapper javadocs for more information
+struts.freemarker.wrapper.altMap=true
+
+### configure the XSLTResult class to use stylesheet caching.
+### Set to true for developers and false for production.
+struts.xslt.nocache=false
+
+### END SNIPPET: complete_file
diff --git a/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/xwork-conversion.properties b/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/xwork-conversion.properties
new file mode 100644
index 0000000..e4f632b
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/resources/com/apress/pss/struts/xwork-conversion.properties
@@ -0,0 +1,4 @@
+# SAF2 global conversion goes here
+# eg.
+# java.util.Date=com.myComp.myApp.DateConverter
+
diff --git a/ch09/ch10/struts-example/src/main/resources/struts.xml b/ch09/ch10/struts-example/src/main/resources/struts.xml
new file mode 100644
index 0000000..663568d
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/resources/struts.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+ /jsp/index.jsp
+
+
+ /jsp/index.jsp
+ /jsp/helloWorld.jsp
+
+
+
diff --git a/ch09/ch10/struts-example/src/main/webapp/WEB-INF/decorators.xml b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/decorators.xml
new file mode 100644
index 0000000..73e7065
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/decorators.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ /nodecorate/*
+ /styles/*
+ /scripts/*
+ /images/*
+ /dojo/*
+ /struts/*
+
+
+
+ /*
+
+
+
diff --git a/ch09/ch10/struts-example/src/main/webapp/WEB-INF/decorators/main.jsp b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/decorators/main.jsp
new file mode 100644
index 0000000..77aaaae
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/decorators/main.jsp
@@ -0,0 +1,86 @@
+
+
+<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
+<%@taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %>
+<%@taglib prefix="page" uri="http://www.opensymphony.com/sitemesh/page" %>
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Main Content
+
+
+
+
+
+
Sub Content
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/struts-example/src/main/webapp/WEB-INF/dwr.xml b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/dwr.xml
new file mode 100644
index 0000000..7b31e18
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/dwr.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ ]]>
+
+
diff --git a/ch09/ch10/struts-example/src/main/webapp/WEB-INF/sitemesh.xml b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/sitemesh.xml
new file mode 100644
index 0000000..39bafc7
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/sitemesh.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/struts-example/src/main/webapp/WEB-INF/web.xml b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fdcf47f
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,71 @@
+
+
+
+
+ Struts 2 - Maven Archetype - Starter
+
+
+ contextConfigLocation
+ classpath*:applicationContext*.xml
+
+
+
+
+
+ springSecurityFilterChain
+
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ action2
+ org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
+
+
+ springSecurityFilterChain
+ /*
+
+
+ action2
+ /*
+
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+
+ dwr
+ uk.ltd.getahead.dwr.DWRServlet
+
+ debug
+ true
+
+
+
+ jspSupportServlet
+ org.apache.struts2.views.JspSupportServlet
+ 5
+
+
+
+ dwr
+ /dwr/*
+
+
+
+
+
+ index.jsp
+ default.jsp
+ index.html
+
+
+
diff --git a/ch09/ch10/struts-example/src/main/webapp/index.jsp b/ch09/ch10/struts-example/src/main/webapp/index.jsp
new file mode 100644
index 0000000..18cf3e1
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/index.jsp
@@ -0,0 +1,2 @@
+
+<% response.sendRedirect("index.action"); %>
diff --git a/ch09/ch10/struts-example/src/main/webapp/jsp/helloWorld.jsp b/ch09/ch10/struts-example/src/main/webapp/jsp/helloWorld.jsp
new file mode 100644
index 0000000..c8f099a
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/jsp/helloWorld.jsp
@@ -0,0 +1 @@
+Pagina Segura
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/jsp/index.jsp b/ch09/ch10/struts-example/src/main/webapp/jsp/index.jsp
new file mode 100644
index 0000000..f9987ff
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/jsp/index.jsp
@@ -0,0 +1 @@
+Pagina simple
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/forms.css b/ch09/ch10/struts-example/src/main/webapp/styles/forms.css
new file mode 100644
index 0000000..c643a48
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/forms.css
@@ -0,0 +1,100 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* FORM ELEMENTS */
+ form {
+ margin:0;
+ padding:0;
+ }
+ form div,
+ form p {
+ font-size: 1em;
+ margin: 0 0 1em 0;
+ padding: 0;
+ }
+ label {
+ font-weight: bold;
+ }
+ fieldset {
+ border: 1px solid #eee;
+ padding: 5px 10px;
+ margin: 0 0 1.5em 0;
+ }
+ fieldset legend {
+ color: #666;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin: 0 0 0 0px;
+ padding: 0;
+ background-color: white;
+ }
+ * html fieldset legend {
+ margin: 0 0 10px -10px;
+ }
+ fieldset ul {
+ list-style: none;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ }
+ fieldset ul li {
+ list-style: none;
+ margin: 0 0 0.5em 0;
+ padding: 0;
+ }
+
+
+ input, select, textarea {
+ font-size:1em;
+ font-family: arial, helvetica, verdana, sans-serif;
+
+ margin: 0;
+ padding: 2px;
+ }
+
+ input, select {
+ vertical-align:middle;
+ }
+ textarea {
+ width: 200px;
+ height: 8em;
+ }
+
+ input.check {
+ border: none;
+ width: auto;
+ height: auto;
+ margin: 0;
+ }
+ input.radio {
+ border: none;
+ width: auto;
+ height: auto;
+ margin: 0;
+ }
+ input.file {
+ height: auto;
+ width: 250px;
+ }
+ input.readonly {
+ background-color: transparent;
+ border: none;
+ }
+ input.button {
+ width: 10em;
+ border:1px solid black;
+ background-color: #ddd;
+ }
+ input.image {
+ border: none;
+ width: auto;
+ height: auto;
+ }
+
+ form div.submit {
+ margin: 1em 0;
+ }
+ form div.submit input {
+ height: 2em;
+ width: 15em;
+ }
+/* END FORM ELEMENTS */
+
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/layout-1col.css b/ch09/ch10/struts-example/src/main/webapp/styles/layout-1col.css
new file mode 100644
index 0000000..236fb12
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/layout-1col.css
@@ -0,0 +1,27 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-horizontal.css");
+
+/* NAV BAR AT THE TOP AND ONE COLUMN OF CONTENT */
+ div#content {
+ position: relative;
+ width: 701px;
+
+ margin: 0 auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ width: 100%;
+ }
+ div#local {
+ display: none;
+ }
+ div#sub {
+ display: none;
+ }
+ div#nav {
+ display: none;
+ }
+/* END CONTENT */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/layout-navleft-1col.css b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navleft-1col.css
new file mode 100644
index 0000000..7b13113
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navleft-1col.css
@@ -0,0 +1,31 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-vertical.css");
+
+/* NAV BAR ON THE LEFT AND ONE COLUMN OF CONTENT */
+ div#content {
+ position: relative;
+ width: 780px;
+
+ margin: 0 auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ float: right;
+ width: 560px;
+ display: inline;
+ }
+ div#local {
+ display: none;
+ }
+ div#sub {
+ display: none;
+ }
+ div#nav {
+ float: left;
+ width: 200px;
+ display: inline;
+ }
+/* END CONTENT */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/layout-navleft-2col.css b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navleft-2col.css
new file mode 100644
index 0000000..4a79b55
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navleft-2col.css
@@ -0,0 +1,39 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-vertical.css");
+
+/* NAV BAR ON THE LEFT AND TWO COLUMNS OF CONTENT */
+ div#content {
+ position: relative;
+ width: 780px;
+
+ margin: 0 auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ float: right;
+ width: 340px;
+ display: inline;
+
+ margin-right: 220px;
+ margin-left: -220px;
+ }
+ div#local {
+ display: none;
+ }
+ div#sub {
+ float: right;
+ width: 200px;
+ display: inline;
+
+ margin-right: -340px;
+ margin-left: 200px;
+ }
+ div#nav {
+ float: left;
+ width: 200px;
+ display: inline;
+ }
+/* END CONTENT */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-1col.css b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-1col.css
new file mode 100644
index 0000000..97241dd
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-1col.css
@@ -0,0 +1,32 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-horizontal.css");
+
+/* NAV BAR AT THE TOP AND ONE COLUMN OF CONTENT */
+ div#content {
+ position: relative;
+ width: 701px;
+
+ margin: 0 auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ width: 100%;
+ }
+ div#local {
+ width: 100%;
+ }
+ div#sub {
+ width: 100%;
+ }
+ div#nav {
+ position: absolute;
+ top: -15px;
+ left: 0;
+ width: 100%;
+
+ text-align: left;
+ }
+/* END CONTENT */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-3col.css b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-3col.css
new file mode 100644
index 0000000..2e58281
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-3col.css
@@ -0,0 +1,43 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-horizontal.css");
+
+/* NAV BAR AT THE TOP, LOCAL NAV ON THE LEFT AND TWO COLUMNS OF CONTENT */
+ div#content {
+ position: relative;
+ width: 701px;
+
+ margin: 0 auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ float: left;
+ width: 300px;
+ display: inline;
+
+ margin-right: -200px;
+ margin-left: 200px;
+ }
+ div#sub {
+ float: right;
+ width: 180px;
+ display: inline;
+ }
+ div#local {
+ float: left;
+ width: 180px;
+ display: inline;
+
+ margin-left: -300px;
+ }
+ div#nav {
+ position: absolute;
+ top: -15px;
+ left: 0;
+ width: 701px;
+
+ text-align: left;
+ }
+/* END CONTENT */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-localleft.css b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-localleft.css
new file mode 100644
index 0000000..448558f
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-localleft.css
@@ -0,0 +1,36 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-horizontal.css");
+
+/* NAV BAR AT THE TOP, LOCAL NAVIGATION ON THE LEFT AND ONE COLUMN OF CONTENT */
+ div#content {
+ position: relative;
+ width: 701px;
+
+ margin: 0 auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ float: right;
+ width: 500px;
+ display: inline;
+ }
+ div#local {
+ float: left;
+ width: 200px;
+ display: inline;
+ }
+ div#sub {
+ display: none;
+ }
+ div#nav {
+ position: absolute;
+ top: -15px;
+ left: 0;
+ width: 100%;
+
+ text-align: left;
+ }
+/* END CONTENT */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-subright.css b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-subright.css
new file mode 100644
index 0000000..6c3cdfe
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/layout-navtop-subright.css
@@ -0,0 +1,36 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+@import url("nav-horizontal.css");
+
+/* NAV BAR AT THE TOP AND TWO COLUMNS OF CONTENT */
+ div#content {
+ position: relative;
+ width: 701px;
+
+ margin: 0 auto 20px auto;
+ padding: 0;
+
+ text-align: left;
+ }
+ div#main {
+ float: left;
+ width: 480px;
+ display: inline;
+ }
+ div#sub {
+ float: right;
+ width: 200px;
+ display: inline;
+ }
+ div#local {
+ display: none;
+ }
+ div#nav {
+ position: absolute;
+ top: -15px;
+ left: 0;
+ width: 100%;
+
+ text-align: left;
+ }
+/* END CONTENT */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/layout.css b/ch09/ch10/struts-example/src/main/webapp/styles/layout.css
new file mode 100644
index 0000000..31a3426
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/layout.css
@@ -0,0 +1,125 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* SITE SPECIFIC LAYOUT */
+ body {
+ margin: 0;
+ padding: 0;
+
+ background: white;
+
+ text-align: center;
+ }
+ div#page {
+ width: 780px;
+
+ margin: 0 auto;
+ padding: 0;
+
+ background: white;
+ text-align: center;
+ }
+
+ /* HEADER */
+ div#header {
+ margin: 0 0 5em 0;
+ padding: 40px 20px;
+
+ color: white;
+ background: black;
+
+ text-align: left;
+ }
+ div#branding {
+ float: left;
+ width: 40%;
+
+ margin: 0;
+ padding: 10px 0 10px 20px;
+
+ text-align: left;
+ }
+ div#search {
+ float: right;
+ width: 49%;
+
+ margin: 0;
+ padding: 16px 20px 0 0;
+
+ text-align: right;
+ }
+ /* END HEADER */
+
+
+ /* CONTENT */
+ div#content {
+
+ }
+
+ /* MAIN */
+ div#main {
+
+ }
+ /* END MAIN */
+
+ /* SUB */
+ div#sub {
+
+ }
+ /* END SUB */
+
+ /* END CONTENT */
+
+
+ /* FOOTER */
+ div#footer {
+ color: white;
+ background-color: black;
+ }
+ div#footer p {
+ font-size: 0.8em;
+
+ margin: 0;
+ padding: 15px;
+ }
+ /* END FOOTER */
+/* END LAYOUT */
+
+
+
+
+/* UL.SUBNAV */
+ ul.subnav {
+ margin: 0;
+ padding: 0;
+
+ font-size: 0.8em;
+ list-style: none;
+ }
+ ul.subnav li {
+ margin: 0 0 1em 0;
+ padding: 0;
+ list-style: none;
+ }
+ ul.subnav li a,
+ ul.subnav li a:link,
+ ul.subnav li a:visited,
+ ul.subnav li a:active {
+ text-decoration: none;
+ font-weight: bold;
+ color: black;
+ }
+ ul.subnav li a:hover {
+ text-decoration: underline;
+ }
+ ul.subnav li strong {
+ padding: 0 0 0 12px;
+ background: url("../i/subnav-highlight.gif") left top no-repeat transparent;
+ }
+ ul.subnav li strong a,
+ ul.subnav li strong a:link,
+ ul.subnav li strong a:visited,
+ ul.subnav li strong a:active {
+ color: white;
+ background-color: black;
+ }
+/* END UL.SUBNAV */
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/main.css b/ch09/ch10/struts-example/src/main/webapp/styles/main.css
new file mode 100644
index 0000000..c72a441
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/main.css
@@ -0,0 +1,21 @@
+/*
+ Css Framework
+ =============
+ - see http://www.contentwithstyle.co.uk/Articles/17/a-css-framework
+ for more info.
+*/
+@import url("tools.css");
+@import url("typo.css");
+@import url("forms.css");
+/*
+ Swap layout stylesheet:
+ layout-navtop-localleft.css
+ layout-navtop-subright.css
+ layout-navtop-3col.css
+ layout-navtop-1col.css
+ layout-navleft-1col.css
+ layout-navleft-2col.css
+*/
+@import url("layout-navtop-localleft.css");
+@import url("layout.css");
+
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/nav-horizontal.css b/ch09/ch10/struts-example/src/main/webapp/styles/nav-horizontal.css
new file mode 100644
index 0000000..ec48d91
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/nav-horizontal.css
@@ -0,0 +1,80 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* NAV */
+ div#nav {
+ font-size: 0.8em;
+ }
+ * html div#nav {
+ /* hide ie/mac \*/
+ height: 1%;
+ /* end hide */
+ }
+ div#nav div.wrapper {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ }
+ div#nav ul {
+ width: auto;
+ width: 100%;
+
+ margin: 0;
+ padding: 0;
+
+ line-height: 1em;
+ list-style: none;
+ }
+ div#nav li {
+ float: left;
+ display: inline;
+
+ list-style: none;
+
+ margin: 0;
+ padding: 0;
+
+ line-height: 1em;
+ border-right: 1px solid #aaa;
+ }
+ div#nav li.last {
+ border-right: none;
+ }
+ div#nav a,
+ div#nav a:link,
+ div#nav a:active,
+ div#nav a:visited {
+ display: inline-block;
+ /* hide from ie/mac \*/
+ display: block;
+ /* end hide */
+ font-weight: bold;
+ text-decoration: none;
+
+ margin: 0;
+ padding: 5px 38px 5px 38px;
+
+ color: black;
+ background: #ddd;
+ }
+ div#nav a:hover {
+ text-decoration: underline;
+ }
+ div#nav strong {
+ display: inline-block;
+ /* hide from ie/mac \*/
+ display: block;
+ /* end hide */
+
+ color: white;
+ background: black;
+ }
+ div#nav strong a,
+ div#nav strong a:link,
+ div#nav strong a:active,
+ div#nav strong a:visited,
+ div#nav strong a:hover {
+ color: white;
+ background-color: black;
+ }
+/* END NAV */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/nav-vertical.css b/ch09/ch10/struts-example/src/main/webapp/styles/nav-vertical.css
new file mode 100644
index 0000000..f58aea6
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/nav-vertical.css
@@ -0,0 +1,79 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* NAV */
+ div#nav {
+ font-size: 0.8em;
+ }
+ * html div#nav {
+ /* hide ie/mac \*/
+ height: 1%;
+ /* end hide */
+ }
+ div#nav div.wrapper {
+ width: 100%;
+
+ background: #ddd;
+ }
+ div#nav ul {
+ width: auto;
+ width: 100%;
+
+ margin: 0;
+ padding: 0;
+
+ line-height: 1em;
+ list-style: none;
+ }
+ div#nav li {
+ display: block;
+
+ list-style: none;
+
+ margin: 0;
+ padding: 0;
+
+ line-height: 1em;
+ }
+ * html div#nav li {
+ /* hide ie/mac \*/
+ height: 1%;
+ /* end hide */
+ }
+ div#nav li.last {
+
+ }
+ div#nav a,
+ div#nav a:link,
+ div#nav a:active,
+ div#nav a:visited {
+ display: block;
+
+ font-weight: bold;
+ text-decoration: none;
+
+ margin: 0;
+ padding: 5px 10px 5px 10px;
+
+ color: black;
+ background: white;
+ }
+ div#nav a:hover {
+ color: white;
+ background: black;
+ text-decoration: underline;
+ }
+ div#nav strong {
+ display: block;
+
+ color: white;
+ background: black;
+ }
+ div#nav strong a,
+ div#nav strong a:link,
+ div#nav strong a:active,
+ div#nav strong a:visited,
+ div#nav strong a:hover {
+ color: white;
+ background-color: black;
+ }
+/* END NAV */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/tools.css b/ch09/ch10/struts-example/src/main/webapp/styles/tools.css
new file mode 100644
index 0000000..0f5607a
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/tools.css
@@ -0,0 +1,68 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* clearing */
+ .stretch,
+ .clear {
+ clear:both;
+ height:1px;
+ margin:0;
+ padding:0;
+ font-size: 15px;
+ line-height: 1px;
+ }
+ .clearfix:after {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+ }
+ * html>body .clearfix {
+ display: inline-block;
+ width: 100%;
+ }
+
+ * html .clearfix {
+ /* Hides from IE-mac \*/
+ height: 1%;
+ /* End hide from IE-mac */
+ }
+/* end clearing */
+
+
+/* replace */
+ .replace {
+ display:block;
+
+ background-repeat: no-repeat;
+ background-position: left top;
+ background-color:transparent;
+ }
+ /* tidy these up */
+ .replace * {
+ text-indent: -10000px;
+ display:block;
+
+ background-repeat: no-repeat;
+ background-position: left top;
+ background-color:transparent;
+ }
+ .replace a {
+ text-indent:0;
+ }
+ .replace a span {
+ text-indent:-10000px;
+ }
+/* end replace */
+
+
+/* accessibility */
+ span.accesskey {
+ text-decoration:none;
+ }
+ .accessibility {
+ position: absolute;
+ top: -999em;
+ left: -999em;
+ }
+/* end accessibility */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/main/webapp/styles/typo.css b/ch09/ch10/struts-example/src/main/webapp/styles/typo.css
new file mode 100644
index 0000000..cedc697
--- /dev/null
+++ b/ch09/ch10/struts-example/src/main/webapp/styles/typo.css
@@ -0,0 +1,177 @@
+/* A CSS Framework by Mike Stenhouse of Content with Style */
+
+/* TYPOGRAPHY */
+ body {
+ text-align: left;
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
+ font-size: 76%;
+ line-height: 1em;
+ color: #333;
+ }
+ div {
+ font-size: 1em;
+ }
+ img {
+ border: 0;
+ }
+
+/* LINKS */
+ a,
+ a:link
+ a:active {
+ color: blue;
+ background-color: white;
+ text-decoration: underline;
+ }
+ a:visited {
+ color: purple;
+ background-color: transparent;
+ }
+ a:hover {
+ color: white;
+ background-color: black;
+ text-decoration: none;
+ }
+/* END LINKS */
+
+/* HEADINGS */
+ h1 {
+ font-size: 2em;
+ line-height: 1.5em;
+ margin: 0 0 0.5em 0;
+ padding: 0;
+ color: black;
+ }
+ h2 {
+ font-size: 1.5em;
+ line-height: 1.5em;
+ margin: 0 0 0.5em 0;
+ padding: 0;
+ color: black;
+ }
+ h3 {
+ font-size: 1.3em;
+ line-height: 1.3em;
+ margin: 0 0 0.5em 0;
+ padding:0;
+ color: black;
+ }
+ h4 {
+ font-size: 1.2em;
+ line-height: 1.3em;
+ margin: 0 0 0.25em 0;
+ padding: 0;
+ color: black;
+ }
+ h5 {
+ font-size: 1.1em;
+ line-height: 1.3em;
+ margin: 0 0 0.25em 0;
+ padding: 0;
+ color: black;
+ }
+ h6 {
+ font-size: 1em;
+ line-height: 1.3em;
+ margin: 0 0 0.25em 0;
+ padding: 0;
+ color: black;
+ }
+/* END HEADINGS */
+
+/* TEXT */
+ p {
+ font-size: 1em;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ line-height:1.4em;
+ }
+ blockquote {
+ border-left:10px solid #ddd;
+ margin-left:10px;
+ }
+ pre {
+ font-family: monospace;
+ font-size: 1.0em;
+ }
+ strong, b {
+ font-weight: bold;
+ }
+ em, i {
+ font-style:italic;
+ }
+ code {
+ font-family: "Courier New", Courier, monospace;
+ font-size: 1em;
+ white-space: pre;
+ }
+/* END TEXT */
+
+/* LISTS */
+ ul {
+ line-height:1.4em;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ }
+ ul li {
+ margin: 0 0 0.25em 30px;
+ padding: 0;
+ }
+ ol {
+ font-size: 1.0em;
+ line-height: 1.4em;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ }
+ ol li {
+ font-size: 1.0em;
+ margin: 0 0 0.25em 30px;
+ padding: 0;
+ }
+ dl {
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ line-height: 1.4em;
+ }
+ dl dt {
+ font-weight: bold;
+ margin: 0.25em 0 0.25em 0;
+ padding: 0;
+ }
+ dl dd {
+ margin: 0 0 0 30px;
+ padding: 0;
+ }
+/* END LISTS */
+
+
+/* TABLE */
+ table {
+ font-size: 1em;
+ margin: 0 0 1.5em 0;
+ padding: 0;
+ }
+ table caption {
+ font-weight: bold;
+ margin: 0 0 0 0;
+ padding: 0 0 1.5em 0;
+ }
+ th {
+ font-weight: bold;
+ text-align: left;
+ }
+ td {
+ font-size: 1em;
+ }
+/* END TABLE */
+
+ hr {
+ display: none;
+ }
+ div.hr {
+ height: 1px;
+ margin: 1.5em 10px;
+ border-bottom: 1px dotted black;
+ }
+
+/* END TYPOGRAPHY */
\ No newline at end of file
diff --git a/ch09/ch10/struts-example/src/test/java/com/apress/pss/struts/HelloWorldActionTest.java b/ch09/ch10/struts-example/src/test/java/com/apress/pss/struts/HelloWorldActionTest.java
new file mode 100644
index 0000000..9edfb80
--- /dev/null
+++ b/ch09/ch10/struts-example/src/test/java/com/apress/pss/struts/HelloWorldActionTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.apress.pss.struts;
+
+import junit.framework.TestCase;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ *
+ */
+public class HelloWorldActionTest extends TestCase {
+
+ public void testHelloWorldAction() throws Exception {
+ HelloWorldAction action = new HelloWorldAction();
+ String result = action.execute();
+ assertEquals(Action.SUCCESS, result);
+ }
+}
+
diff --git a/ch09/ch10/struts-example/src/test/java/com/apress/pss/struts/IndexActionTest.java b/ch09/ch10/struts-example/src/test/java/com/apress/pss/struts/IndexActionTest.java
new file mode 100644
index 0000000..0cec382
--- /dev/null
+++ b/ch09/ch10/struts-example/src/test/java/com/apress/pss/struts/IndexActionTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.apress.pss.struts;
+
+import junit.framework.TestCase;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ *
+ */
+public class IndexActionTest extends TestCase {
+
+ public void testIndexAction() throws Exception {
+ IndexAction action = new IndexAction();
+ String result = action.execute();
+ assertEquals(Action.SUCCESS, result);
+ }
+}
diff --git a/ch09/ch10/webflow-example/.classpath b/ch09/ch10/webflow-example/.classpath
new file mode 100644
index 0000000..c1b7e99
--- /dev/null
+++ b/ch09/ch10/webflow-example/.classpath
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/webflow-example/.project b/ch09/ch10/webflow-example/.project
new file mode 100644
index 0000000..134a9ec
--- /dev/null
+++ b/ch09/ch10/webflow-example/.project
@@ -0,0 +1,48 @@
+
+
+ webflow-example
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.springframework.ide.eclipse.core.springbuilder
+
+
+
+
+
+ org.springframework.ide.eclipse.core.springnature
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/ch09/ch10/webflow-example/.settings/.jsdtscope b/ch09/ch10/webflow-example/.settings/.jsdtscope
new file mode 100644
index 0000000..b46b920
--- /dev/null
+++ b/ch09/ch10/webflow-example/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/webflow-example/.settings/com.springsource.sts.config.flow.prefs b/ch09/ch10/webflow-example/.settings/com.springsource.sts.config.flow.prefs
new file mode 100644
index 0000000..65d0db0
--- /dev/null
+++ b/ch09/ch10/webflow-example/.settings/com.springsource.sts.config.flow.prefs
@@ -0,0 +1,3 @@
+//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/webflow\:/webflow-example/src/main/webapp/WEB-INF/flows/products/product-flow.xml=\n\n\n \n \n \n\n \n \n \n\n \n \n \n
+//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/webflow\:/webflow-example/src/main/webapp/WEB-INF/flows/products/product.xml=\n\n\n \n \n \n\n \n \n \n\n \n \n \n
+eclipse.preferences.version=1
diff --git a/ch09/ch10/webflow-example/.settings/org.eclipse.jdt.core.prefs b/ch09/ch10/webflow-example/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..45a6e0e
--- /dev/null
+++ b/ch09/ch10/webflow-example/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/ch09/ch10/webflow-example/.settings/org.eclipse.m2e.core.prefs b/ch09/ch10/webflow-example/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ch09/ch10/webflow-example/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/ch09/ch10/webflow-example/.settings/org.eclipse.wst.common.component b/ch09/ch10/webflow-example/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..0244542
--- /dev/null
+++ b/ch09/ch10/webflow-example/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/webflow-example/.settings/org.eclipse.wst.common.project.facet.core.xml b/ch09/ch10/webflow-example/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..bca3237
--- /dev/null
+++ b/ch09/ch10/webflow-example/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ch09/ch10/webflow-example/.settings/org.eclipse.wst.jsdt.ui.superType.container b/ch09/ch10/webflow-example/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/ch09/ch10/webflow-example/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/ch09/ch10/webflow-example/.settings/org.eclipse.wst.jsdt.ui.superType.name b/ch09/ch10/webflow-example/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/ch09/ch10/webflow-example/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/ch09/ch10/webflow-example/pom.xml b/ch09/ch10/webflow-example/pom.xml
new file mode 100644
index 0000000..3a6d12f
--- /dev/null
+++ b/ch09/ch10/webflow-example/pom.xml
@@ -0,0 +1,123 @@
+
+ 4.0.0
+ com.apress.pss
+ webflow-example
+ war
+ 1.0-SNAPSHOT
+ webflow-example Maven Webapp
+ http://maven.apache.org
+
+ 3.1.1.RELEASE
+
+
+
+
+
+ org.springframework
+ spring-core
+ ${org.springframework.version}
+
+
+
+ org.springframework
+ spring-expression
+ ${org.springframework.version}
+
+
+ org.springframework
+ spring-beans
+ ${org.springframework.version}
+
+
+ org.springframework
+ spring-aop
+ ${org.springframework.version}
+
+
+
+
+ org.springframework
+ spring-context
+ ${org.springframework.version}
+
+
+
+ org.springframework
+ spring-context-support
+ ${org.springframework.version}
+
+
+
+ org.springframework
+ spring-web
+ ${org.springframework.version}
+
+
+
+ org.springframework
+ spring-webmvc
+ ${org.springframework.version}
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+
+
+ junit
+ junit
+ 4.5
+ test
+
+
+ org.springframework.security
+ spring-security-core
+ 3.1.0.RELEASE
+
+
+ org.springframework.security
+ spring-security-config
+ 3.1.0.RELEASE
+
+
+ org.springframework.security
+ spring-security-web
+ 3.1.0.RELEASE
+
+
+ org.springframework.webflow
+ spring-webflow
+ 2.3.1.RELEASE
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ commons-codec
+ commons-codec
+ 1.3
+
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 8.1.1.v20120215
+
+
+
+ 8080
+ 60000
+
+
+
+
+
+ webflow-example
+
+
diff --git a/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/CustomSecurityListener.java b/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/CustomSecurityListener.java
new file mode 100644
index 0000000..fa336f0
--- /dev/null
+++ b/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/CustomSecurityListener.java
@@ -0,0 +1,99 @@
+package com.apress.pss.webflow.security;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.webflow.definition.FlowDefinition;
+import org.springframework.webflow.definition.StateDefinition;
+import org.springframework.webflow.definition.TransitionDefinition;
+import org.springframework.webflow.execution.EnterStateVetoException;
+import org.springframework.webflow.execution.FlowExecutionListenerAdapter;
+import org.springframework.webflow.execution.RequestContext;
+import org.springframework.webflow.security.SecurityRule;
+
+/**
+ * Flow security integration with Spring Security
+ *
+ * @author Scott Andrews
+ */
+public class CustomSecurityListener extends FlowExecutionListenerAdapter {
+
+ private AccessDecisionManager accessDecisionManager;
+
+ /**
+ * Get the access decision manager that makes flow authorization decisions.
+ * @return the decision manager
+ */
+ public AccessDecisionManager getAccessDecisionManager() {
+ return accessDecisionManager;
+ }
+
+ /**
+ * Set the access decision manager that makes flow authorization decisions.
+ * @param accessDecisionManager the decision manager to user
+ */
+ public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) {
+ this.accessDecisionManager = accessDecisionManager;
+ }
+
+ public void sessionCreating(RequestContext context, FlowDefinition definition) {
+ SecurityRule rule = (SecurityRule) definition.getAttributes().get(SecurityRule.SECURITY_ATTRIBUTE_NAME);
+ if (rule != null) {
+ decide(rule, definition);
+ }
+ }
+
+ public void stateEntering(RequestContext context, StateDefinition state) throws EnterStateVetoException {
+ SecurityRule rule = (SecurityRule) state.getAttributes().get(SecurityRule.SECURITY_ATTRIBUTE_NAME);
+ if (rule != null) {
+ decide(rule, state);
+ }
+ }
+
+ public void transitionExecuting(RequestContext context, TransitionDefinition transition) {
+ SecurityRule rule = (SecurityRule) transition.getAttributes().get(SecurityRule.SECURITY_ATTRIBUTE_NAME);
+ if (rule != null) {
+ decide(rule, transition);
+ }
+ }
+
+ /**
+ * Performs a Spring Security authorization decision. Decision will use the provided AccessDecisionManager. If no
+ * AccessDecisionManager is provided a role based manager will be selected according to the comparison type of the
+ * rule.
+ * @param rule the rule to base the decision
+ * @param object the execution listener phase
+ */
+ protected void decide(SecurityRule rule, Object object) {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ Collection configAttributes = getConfigAttributes(rule);
+ if (accessDecisionManager != null) {
+ accessDecisionManager.decide(authentication, object, configAttributes);
+ } else {
+ throw new NullPointerException("Access decision manager has to be injected");
+ }
+ }
+
+
+ /**
+ * Convert SecurityRule into a form understood by Spring Security
+ * @param rule the rule to convert
+ * @return list of ConfigAttributes for Spring Security
+ */
+ protected Collection getConfigAttributes(SecurityRule rule) {
+ List configAttributes = new ArrayList();
+ for (Object attribute : rule.getAttributes()) {
+ configAttributes.add(new SecurityConfig((String)attribute));
+ }
+ return configAttributes;
+ }
+}
diff --git a/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/DefaultFlowStateSecurityExpressionHandler.java b/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/DefaultFlowStateSecurityExpressionHandler.java
new file mode 100644
index 0000000..731fcd9
--- /dev/null
+++ b/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/DefaultFlowStateSecurityExpressionHandler.java
@@ -0,0 +1,18 @@
+package com.apress.pss.webflow.security;
+
+import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
+import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.core.Authentication;
+import org.springframework.webflow.engine.State;
+
+public class DefaultFlowStateSecurityExpressionHandler extends AbstractSecurityExpressionHandler{
+
+ @Override
+ protected SecurityExpressionRoot createSecurityExpressionRoot(
+ Authentication authentication, State invocation) {
+ SecurityExpressionRoot root = new StateSecurityExpressionRoot(authentication, invocation);
+ root.setPermissionEvaluator(getPermissionEvaluator());
+ return root;
+ }
+
+}
diff --git a/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/StateExpressionVoter.java b/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/StateExpressionVoter.java
new file mode 100644
index 0000000..4bcc5b6
--- /dev/null
+++ b/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/StateExpressionVoter.java
@@ -0,0 +1,36 @@
+package com.apress.pss.webflow.security;
+
+import java.util.Collection;
+
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.security.access.AccessDecisionVoter;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.expression.ExpressionUtils;
+import org.springframework.security.access.expression.SecurityExpressionHandler;
+import org.springframework.security.core.Authentication;
+import org.springframework.webflow.engine.State;
+
+public class StateExpressionVoter implements AccessDecisionVoter {
+
+ private SecurityExpressionHandler expressionHandler = new DefaultFlowStateSecurityExpressionHandler();
+ public boolean supports(ConfigAttribute attribute) {
+ return true;
+ }
+
+ public boolean supports(Class> clazz) {
+ return true;
+ }
+
+ public int vote(Authentication authentication, State object,
+ Collection attributes) {
+ EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, object);
+ ExpressionParser parser = new SpelExpressionParser();
+ Expression exp = parser.parseExpression(attributes.iterator().next().getAttribute());
+ return ExpressionUtils.evaluateAsBoolean(exp, ctx) ?
+ ACCESS_GRANTED : ACCESS_DENIED;
+ }
+
+}
diff --git a/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/StateSecurityExpressionRoot.java b/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/StateSecurityExpressionRoot.java
new file mode 100644
index 0000000..a4cb698
--- /dev/null
+++ b/ch09/ch10/webflow-example/src/main/java/com/apress/pss/webflow/security/StateSecurityExpressionRoot.java
@@ -0,0 +1,14 @@
+package com.apress.pss.webflow.security;
+
+import org.springframework.security.access.expression.SecurityExpressionRoot;
+import org.springframework.security.core.Authentication;
+import org.springframework.webflow.engine.State;
+
+public class StateSecurityExpressionRoot extends SecurityExpressionRoot {
+ private State state;
+ public StateSecurityExpressionRoot(Authentication a, State state) {
+ super(a);
+ this.state = state;
+ }
+
+}
diff --git a/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/applicationContext-security.xml b/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/applicationContext-security.xml
new file mode 100644
index 0000000..5e8127c
--- /dev/null
+++ b/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/applicationContext-security.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/example-webflow.xml b/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/example-webflow.xml
new file mode 100644
index 0000000..7a34cd0
--- /dev/null
+++ b/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/example-webflow.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/flows/products/buy.jsp b/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/flows/products/buy.jsp
new file mode 100644
index 0000000..4f491eb
--- /dev/null
+++ b/ch09/ch10/webflow-example/src/main/webapp/WEB-INF/flows/products/buy.jsp
@@ -0,0 +1,7 @@
+
+Ferrari f40
+
+
+You just bough the ferrari F40. We will deliver gift wrapped tomorrow between 9am and 11am
+
+