You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by ka...@apache.org on 2011/07/18 13:10:55 UTC

svn commit: r1147810 [1/2] - in /shiro/trunk: ./ all/ support/ support/guice/ support/guice/src/ support/guice/src/main/ support/guice/src/main/java/ support/guice/src/main/java/org/ support/guice/src/main/java/org/apache/ support/guice/src/main/java/o...

Author: kaosko
Date: Mon Jul 18 11:10:51 2011
New Revision: 1147810

URL: http://svn.apache.org/viewvc?rev=1147810&view=rev
Log:
SHIRO-23 - Integrating Jsecurity with Guice:
- apply Jared Bunting's guice-final.patch with no other changes but added license info
- rat run passes

Added:
    shiro/trunk/support/guice/   (with props)
    shiro/trunk/support/guice/pom.xml
    shiro/trunk/support/guice/src/
    shiro/trunk/support/guice/src/main/
    shiro/trunk/support/guice/src/main/java/
    shiro/trunk/support/guice/src/main/java/org/
    shiro/trunk/support/guice/src/main/java/org/apache/
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/BeanTypeListener.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/DestroyableInjectionListener.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/GuiceEnvironment.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/InitializableInjectionListener.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/LifecycleTypeListener.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroMatchers.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroModule.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroSessionScope.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInterceptorAdapter.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInvocationAdapter.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/ShiroAopModule.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/AbstractInjectionProvider.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/FilterChainResolverProvider.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/GuiceShiroFilter.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/PathMatchingFilterProvider.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/ShiroWebModule.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChain.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChainResolver.java
    shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/WebGuiceEnvironment.java
    shiro/trunk/support/guice/src/test/
    shiro/trunk/support/guice/src/test/java/
    shiro/trunk/support/guice/src/test/java/org/
    shiro/trunk/support/guice/src/test/java/org/apache/
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/BeanTypeListenerTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/DestroyableInjectionListenerTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/GuiceEnvironmentTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/InitializableInjectionListenerTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/LifecycleTypeListenerTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/ShiroMatchersTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/ShiroModuleTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/ShiroSessionScopeTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/aop/
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/aop/AopAllianceMethodInterceptorAdapterTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/aop/AopAllianceMethodInvocationAdapterTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/aop/ShiroAopModuleTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/AbstractInjectionProviderTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/DefaultFiltersTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/FilterChainResolverProviderTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/FilterConfigTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/GuiceShiroFilterTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/PathMatchingFilterProviderTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/ShiroWebModuleTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/SimpleFilterChainResolverTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/SimpleFilterChainTest.java
    shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/web/WebGuiceEnvironmentTest.java
Modified:
    shiro/trunk/all/pom.xml
    shiro/trunk/pom.xml
    shiro/trunk/support/pom.xml

Modified: shiro/trunk/all/pom.xml
URL: http://svn.apache.org/viewvc/shiro/trunk/all/pom.xml?rev=1147810&r1=1147809&r2=1147810&view=diff
==============================================================================
--- shiro/trunk/all/pom.xml (original)
+++ shiro/trunk/all/pom.xml Mon Jul 18 11:10:51 2011
@@ -53,6 +53,10 @@
             <groupId>org.apache.shiro</groupId>
             <artifactId>shiro-spring</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-guice</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

Modified: shiro/trunk/pom.xml
URL: http://svn.apache.org/viewvc/shiro/trunk/pom.xml?rev=1147810&r1=1147809&r2=1147810&view=diff
==============================================================================
--- shiro/trunk/pom.xml (original)
+++ shiro/trunk/pom.xml Mon Jul 18 11:10:51 2011
@@ -85,6 +85,8 @@
         <quartz.version>1.6.1</quartz.version>
         <slf4j.version>1.6.1</slf4j.version>
         <spring.version>3.0.5.RELEASE</spring.version>
+        <guice.version>3.0</guice.version>
+        <guava.version>r09</guava.version>
 
         <!-- Test 3rd-party dependencies: -->
         <easymock.version>3.0</easymock.version>
@@ -460,6 +462,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.shiro</groupId>
+                <artifactId>shiro-guice</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.shiro</groupId>
                 <artifactId>shiro-aspectj</artifactId>
                 <version>${project.version}</version>
             </dependency>
@@ -750,6 +757,26 @@
                 </exclusions>
             </dependency>
             <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>${guava.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.inject</groupId>
+                <artifactId>guice</artifactId>
+                <version>${guice.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.inject.extensions</groupId>
+                <artifactId>guice-multibindings</artifactId>
+                <version>${guice.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.inject.extensions</groupId>
+                <artifactId>guice-servlet</artifactId>
+                <version>${guice.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.opensymphony.quartz</groupId>
                 <artifactId>quartz</artifactId>
                 <version>${quartz.version}</version>

Propchange: shiro/trunk/support/guice/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Jul 18 11:10:51 2011
@@ -0,0 +1 @@
+target

Added: shiro/trunk/support/guice/pom.xml
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/pom.xml?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/pom.xml (added)
+++ shiro/trunk/support/guice/pom.xml Mon Jul 18 11:10:51 2011
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <parent>
+        <groupId>org.apache.shiro</groupId>
+        <artifactId>shiro-root</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>shiro-guice</artifactId>
+    <name>Apache Shiro :: Support :: Guice</name>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <guice.version>3.0</guice.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-web</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject.extensions</groupId>
+            <artifactId>guice-multibindings</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject.extensions</groupId>
+            <artifactId>guice-servlet</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>org.apache.shiro.guice</Bundle-SymbolicName>
+                        <Export-Package>org.apache.shiro.guice*;version=${project.version}</Export-Package>
+                        <Import-Package>
+                            org.apache.shiro*;version="${shiro.osgi.importRange}",
+                            org.aopalliance*;version="[1.0.0, 2.0.0)",
+                            com.google.inject*;version="[3.0.0, 4.0.0)",
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/BeanTypeListener.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/BeanTypeListener.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/BeanTypeListener.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/BeanTypeListener.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.common.primitives.Primitives;
+import com.google.inject.*;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.name.Names;
+import com.google.inject.spi.TypeEncounter;
+import com.google.inject.spi.TypeListener;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.shiro.SecurityUtils;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * TypeListener that injects setter methods on Shiro objects.
+ */
+class BeanTypeListener implements TypeListener {
+    public static final Package SHIRO_GUICE_PACKAGE = ShiroModule.class.getPackage();
+    public static final Package SHIRO_PACKAGE = SecurityUtils.class.getPackage();
+
+    private static Matcher<Class> shiroMatcher = Matchers.inSubpackage(SHIRO_PACKAGE.getName());
+    private static Matcher<Class> shiroGuiceMatcher = Matchers.inSubpackage(SHIRO_GUICE_PACKAGE.getName());
+
+    private static Matcher<Class> classMatcher = ShiroMatchers.ANY_PACKAGE.and(shiroMatcher.and(Matchers.not(shiroGuiceMatcher)));
+
+    public static final Matcher<TypeLiteral> MATCHER = ShiroMatchers.typeLiteral(classMatcher);
+
+    public <I> void hear(TypeLiteral<I> type, final TypeEncounter<I> encounter) {
+        PropertyDescriptor propertyDescriptors[] = PropertyUtils.getPropertyDescriptors(type.getRawType());
+        final Map<PropertyDescriptor, Key<?>> propertyDependencies = new HashMap<PropertyDescriptor, Key<?>>(propertyDescriptors.length);
+        final Provider<Injector> injectorProvider = encounter.getProvider(Injector.class);
+        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+            if (propertyDescriptor.getWriteMethod() != null && Modifier.isPublic(propertyDescriptor.getWriteMethod().getModifiers())) {
+                Type propertyType = propertyDescriptor.getWriteMethod().getGenericParameterTypes()[0];
+                propertyDependencies.put(propertyDescriptor, requiresName(propertyType)
+                        ? Key.get(propertyType, Names.named("shiro." + propertyDescriptor.getName()))
+                        : Key.get(propertyType));
+            }
+        }
+        encounter.register(new MembersInjector<I>() {
+            public void injectMembers(I instance) {
+                for (Map.Entry<PropertyDescriptor, Key<?>> dependency : propertyDependencies.entrySet()) {
+                    try {
+                        Object value = injectorProvider.get().getInstance(dependency.getValue());
+                        dependency.getKey().getWriteMethod().invoke(instance, value);
+
+                    } catch (ConfigurationException e) {
+                        // This is ok, it simply means that we can't fulfill this dependency.
+                        // Is there a better way to do this?
+                    } catch (InvocationTargetException e) {
+                        throw new RuntimeException("Couldn't set property " + dependency.getKey().getDisplayName(), e);
+                    } catch (IllegalAccessException e) {
+                        throw new RuntimeException("We shouldn't have ever reached this point, we don't try to inject to non-accessible methods.", e);
+                    }
+                }
+
+            }
+        });
+    }
+
+    private static boolean requiresName(Type propertyType) {
+        if (propertyType instanceof Class) {
+            Class<?> aClass = (Class<?>) propertyType;
+            return aClass.isPrimitive() || aClass.isEnum() || Primitives.isWrapperType(aClass) || CharSequence.class.isAssignableFrom(aClass);
+        } else {
+            return false;
+        }
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/DestroyableInjectionListener.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/DestroyableInjectionListener.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/DestroyableInjectionListener.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/DestroyableInjectionListener.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.InjectionListener;
+import org.apache.shiro.util.Destroyable;
+
+/**
+ * Injection listener that assists with honoring the {@link org.apache.shiro.util.Destroyable} interface.
+ *
+ * @param <I>
+ */
+class DestroyableInjectionListener<I extends Destroyable> implements InjectionListener<I> {
+    public static final Matcher<TypeLiteral> MATCHER = ShiroMatchers.typeLiteral(Matchers.subclassesOf(Destroyable.class));
+
+    private DestroyableRegistry registry;
+
+    public DestroyableInjectionListener(DestroyableRegistry registry) {
+        this.registry = registry;
+    }
+
+    public void afterInjection(Destroyable injectee) {
+        registry.add(injectee);
+    }
+
+    public static interface DestroyableRegistry {
+        void add(Destroyable destroyable);
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/GuiceEnvironment.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/GuiceEnvironment.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/GuiceEnvironment.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/GuiceEnvironment.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.inject.Inject;
+import org.apache.shiro.env.Environment;
+import org.apache.shiro.mgt.SecurityManager;
+
+class GuiceEnvironment implements Environment {
+    private SecurityManager securityManager;
+
+    @Inject
+    public GuiceEnvironment(SecurityManager securityManager) {
+        this.securityManager = securityManager;
+    }
+
+    public SecurityManager getSecurityManager() {
+        return securityManager;
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/InitializableInjectionListener.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/InitializableInjectionListener.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/InitializableInjectionListener.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/InitializableInjectionListener.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.spi.InjectionListener;
+import org.apache.shiro.util.Initializable;
+
+/**
+ * Injection listener that honors the {@link org.apache.shiro.util.Initializable} interface.
+ *
+ * @param <I>
+ */
+class InitializableInjectionListener<I extends Initializable> implements InjectionListener<I> {
+    public static final Matcher<TypeLiteral> MATCHER = ShiroMatchers.typeLiteral(Matchers.subclassesOf(Initializable.class));
+
+    public void afterInjection(Initializable injectee) {
+        injectee.init();
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/LifecycleTypeListener.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/LifecycleTypeListener.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/LifecycleTypeListener.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/LifecycleTypeListener.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.matcher.Matcher;
+import com.google.inject.spi.InjectionListener;
+import com.google.inject.spi.TypeEncounter;
+import com.google.inject.spi.TypeListener;
+import org.apache.shiro.util.Destroyable;
+import org.apache.shiro.util.Initializable;
+
+
+class LifecycleTypeListener implements TypeListener {
+    public static final Matcher<TypeLiteral> MATCHER = InitializableInjectionListener.MATCHER.or(DestroyableInjectionListener.MATCHER);
+    private DestroyableInjectionListener.DestroyableRegistry registry;
+
+    public LifecycleTypeListener(DestroyableInjectionListener.DestroyableRegistry registry) {
+        this.registry = registry;
+    }
+
+    public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
+        if (InitializableInjectionListener.MATCHER.matches(type)) {
+            encounter.register(this.<I>castListener(new InitializableInjectionListener<Initializable>()));
+        }
+        if (DestroyableInjectionListener.MATCHER.matches(type)) {
+            encounter.register(this.<I>castListener(new DestroyableInjectionListener<Destroyable>(registry)));
+        }
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private <I> InjectionListener<? super I> castListener(InjectionListener<?> listener) {
+        return (InjectionListener<? super I>) listener;
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroMatchers.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroMatchers.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroMatchers.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroMatchers.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.matcher.AbstractMatcher;
+import com.google.inject.matcher.Matcher;
+
+class ShiroMatchers {
+    public static Matcher<Class> ANY_PACKAGE = new AbstractMatcher<Class>() {
+
+        public boolean matches(Class aClass) {
+            return aClass.getPackage() != null;
+        }
+    };
+
+    public static Matcher<TypeLiteral> typeLiteral(final Matcher<Class> classMatcher) {
+        return new AbstractMatcher<TypeLiteral>() {
+
+            public boolean matches(TypeLiteral typeLiteral) {
+                return classMatcher.matches(typeLiteral.getRawType());
+            }
+        };
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroModule.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroModule.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroModule.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroModule.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.common.collect.Sets;
+import com.google.inject.Key;
+import com.google.inject.PrivateModule;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.util.Types;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.env.Environment;
+import org.apache.shiro.mgt.DefaultSecurityManager;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.util.Destroyable;
+
+import javax.annotation.PreDestroy;
+import java.util.Collection;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+
+/**
+ * Sets up Shiro lifecycles within Guice, enables the injecting of Shiro objects, and binds a default
+ * {@link org.apache.shiro.mgt.SecurityManager} and {@link org.apache.shiro.session.mgt.SessionManager}.  At least one realm must be added by using
+ * {@link #bindRealm() bindRealm}.
+ */
+public abstract class ShiroModule extends PrivateModule implements Destroyable {
+
+    private Set<Destroyable> destroyables = Sets.newSetFromMap(new WeakHashMap<Destroyable, Boolean>());
+
+    public void configure() {
+        // setup security manager
+        bindSecurityManager(bind(SecurityManager.class));
+        bindSessionManager(bind(SessionManager.class));
+        bindEnvironment(bind(Environment.class));
+        bindListener(BeanTypeListener.MATCHER, new BeanTypeListener());
+        final DestroyableInjectionListener.DestroyableRegistry registry = new DestroyableInjectionListener.DestroyableRegistry() {
+            public void add(Destroyable destroyable) {
+                ShiroModule.this.add(destroyable);
+            }
+
+            @PreDestroy
+            public void destroy() throws Exception {
+                ShiroModule.this.destroy();
+            }
+        };
+        bindListener(LifecycleTypeListener.MATCHER, new LifecycleTypeListener(registry));
+
+        expose(SecurityManager.class);
+
+        configureShiro();
+        bind(realmCollectionKey())
+                .to(realmSetKey());
+
+        bind(DestroyableInjectionListener.DestroyableRegistry.class).toInstance(registry);
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private Key<Set<Realm>> realmSetKey() {
+        return (Key<Set<Realm>>) Key.get(TypeLiteral.get(Types.setOf(Realm.class)));
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private Key<Collection<Realm>> realmCollectionKey() {
+        return (Key<Collection<Realm>>) Key.get(Types.newParameterizedType(Collection.class, Realm.class));
+    }
+
+    /**
+     * Implement this method in order to configure your realms and any other Shiro customization you may need.
+     */
+    protected abstract void configureShiro();
+
+    /**
+     * This is the preferred manner to bind a realm.  The {@link org.apache.shiro.mgt.SecurityManager} will be injected with any Realm bound
+     * with this method.
+     *
+     * @return a binding builder for a realm
+     */
+    protected final LinkedBindingBuilder<Realm> bindRealm() {
+        Multibinder<Realm> multibinder = Multibinder.newSetBinder(binder(), Realm.class);
+        return multibinder.addBinding();
+    }
+
+    /**
+     * Binds the security manager.  Override this method in order to provide your own security manager binding.
+     * <p/>
+     * By default, a {@link org.apache.shiro.mgt.DefaultSecurityManager} is bound as an eager singleton.
+     *
+     * @param bind
+     */
+    protected void bindSecurityManager(AnnotatedBindingBuilder<? super SecurityManager> bind) {
+        try {
+            bind.toConstructor(DefaultSecurityManager.class.getConstructor(Collection.class)).asEagerSingleton();
+        } catch (NoSuchMethodException e) {
+            throw new ConfigurationException("This really shouldn't happen.  Either something has changed in Shiro, or there's a bug in " + ShiroModule.class.getSimpleName(), e);
+        }
+    }
+
+    /**
+     * Binds the session manager.  Override this method in order to provide your own session manager binding.
+     * <p/>
+     * By default, a {@link org.apache.shiro.session.mgt.DefaultSessionManager} is bound as an eager singleton.
+     *
+     * @param bind
+     */
+    protected void bindSessionManager(AnnotatedBindingBuilder<SessionManager> bind) {
+        bind.to(DefaultSessionManager.class).asEagerSingleton();
+    }
+
+    /**
+     * Binds the environment.  Override this method in order to provide your own environment binding.
+     * <p/>
+     * By default, a {@link GuiceEnvironment} is bound as an eager singleton.
+     *
+     * @param bind
+     */
+    protected void bindEnvironment(AnnotatedBindingBuilder<Environment> bind) {
+        bind.to(GuiceEnvironment.class).asEagerSingleton();
+    }
+
+    /**
+     * Destroys all beans created within this module that implement {@link org.apache.shiro.util.Destroyable}.  Should be called when this
+     * module will no longer be used.
+     *
+     * @throws Exception
+     */
+    public final void destroy() throws Exception {
+        for (Destroyable destroyable : destroyables) {
+            destroyable.destroy();
+        }
+    }
+
+    public void add(Destroyable destroyable) {
+        this.destroyables.add(destroyable);
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroSessionScope.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroSessionScope.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroSessionScope.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/ShiroSessionScope.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.inject.Key;
+import com.google.inject.OutOfScopeException;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.ThreadContext;
+
+/**
+ * Guice scope for Shiro sessions.  Not bound by default.
+ */
+public class ShiroSessionScope implements Scope {
+    public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
+        return new Provider<T>() {
+            public T get() {
+                Subject subject = ThreadContext.getSubject();
+                if (subject == null) {
+                    throw new OutOfScopeException("There is no Shiro Session currently in scope.");
+                }
+                Session session = subject.getSession();
+                T scoped = castSessionAttribute(session);
+                if (scoped == null) {
+                    scoped = unscoped.get();
+                }
+                return scoped;
+            }
+
+            @SuppressWarnings({"unchecked"})
+            private T castSessionAttribute(Session session) {
+                return (T) session.getAttribute(key);
+            }
+
+            @Override
+            public String toString() {
+                return unscoped.toString();
+            }
+        };
+    }
+
+    @Override
+    public String toString() {
+        return "ShiroSessionScope";
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInterceptorAdapter.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInterceptorAdapter.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInterceptorAdapter.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInterceptorAdapter.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.aop;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * Adapts a Shiro {@link org.apache.shiro.aop.MethodInterceptor MethodInterceptor} to an AOPAlliance
+ * {@link org.aopalliance.intercept.MethodInterceptor}.
+ */
+class AopAllianceMethodInterceptorAdapter implements MethodInterceptor {
+    org.apache.shiro.aop.MethodInterceptor shiroInterceptor;
+
+    public AopAllianceMethodInterceptorAdapter(org.apache.shiro.aop.MethodInterceptor shiroInterceptor) {
+        this.shiroInterceptor = shiroInterceptor;
+    }
+
+    public Object invoke(MethodInvocation invocation) throws Throwable {
+        return shiroInterceptor.invoke(new AopAllianceMethodInvocationAdapter(invocation));
+    }
+
+    @Override
+    public String toString() {
+        return "AopAlliance Adapter for " + shiroInterceptor.toString();
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInvocationAdapter.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInvocationAdapter.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInvocationAdapter.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/AopAllianceMethodInvocationAdapter.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.aop;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.Method;
+
+/**
+ * Adapts a Shiro {@link org.apache.shiro.aop.MethodInvocation MethodInvocation} to an AOPAlliance
+ * {@link org.aopalliance.intercept.MethodInvocation}.
+ */
+class AopAllianceMethodInvocationAdapter implements org.apache.shiro.aop.MethodInvocation {
+    private final MethodInvocation mi;
+
+    public AopAllianceMethodInvocationAdapter(MethodInvocation mi) {
+        this.mi = mi;
+    }
+
+    public Method getMethod() {
+        return mi.getMethod();
+    }
+
+    public Object[] getArguments() {
+        return mi.getArguments();
+    }
+
+    public String toString() {
+        return "Method invocation [" + mi.getMethod() + "]";
+    }
+
+    public Object proceed() throws Throwable {
+        return mi.proceed();
+    }
+
+    public Object getThis() {
+        return mi.getThis();
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/ShiroAopModule.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/ShiroAopModule.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/ShiroAopModule.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/aop/ShiroAopModule.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.aop;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.matcher.AbstractMatcher;
+import com.google.inject.matcher.Matchers;
+import org.apache.shiro.aop.AnnotationMethodInterceptor;
+import org.apache.shiro.aop.AnnotationResolver;
+import org.apache.shiro.aop.DefaultAnnotationResolver;
+import org.apache.shiro.authz.aop.*;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * Install this module to enable Shiro AOP functionality in Guice.  You may extend it to add your own Shiro
+ * interceptors, override the default ones, or provide a specific {@link org.apache.shiro.aop.AnnotationResolver}.
+ */
+public class ShiroAopModule extends AbstractModule {
+    @Override
+    protected final void configure() {
+        AnnotationResolver resolver = createAnnotationResolver();
+        configureDefaultInterceptors(resolver);
+        configureInterceptors(resolver);
+    }
+
+    protected final void bindShiroInterceptor(final AnnotationMethodInterceptor methodInterceptor) {
+        bindInterceptor(Matchers.any(), new AbstractMatcher<Method>() {
+            public boolean matches(Method method) {
+                Class<? extends Annotation> annotation = methodInterceptor.getHandler().getAnnotationClass();
+                return method.getAnnotation(annotation) != null
+                        || method.getDeclaringClass().getAnnotation(annotation) != null;
+            }
+        }, new AopAllianceMethodInterceptorAdapter(methodInterceptor));
+    }
+
+    protected AnnotationResolver createAnnotationResolver() {
+        return new DefaultAnnotationResolver();
+    }
+
+    protected void configureDefaultInterceptors(AnnotationResolver resolver) {
+        bindShiroInterceptor(new RoleAnnotationMethodInterceptor(resolver));
+        bindShiroInterceptor(new PermissionAnnotationMethodInterceptor(resolver));
+        bindShiroInterceptor(new AuthenticatedAnnotationMethodInterceptor(resolver));
+        bindShiroInterceptor(new UserAnnotationMethodInterceptor(resolver));
+        bindShiroInterceptor(new GuestAnnotationMethodInterceptor(resolver));
+    }
+
+    protected void configureInterceptors(AnnotationResolver resolver) {
+
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/AbstractInjectionProvider.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/AbstractInjectionProvider.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/AbstractInjectionProvider.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/AbstractInjectionProvider.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.web;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.ProvisionException;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.ProviderWithDependencies;
+
+import java.lang.reflect.Constructor;
+import java.util.Set;
+
+class AbstractInjectionProvider<T> implements ProviderWithDependencies<T> {
+    private Key<T> key;
+
+    @Inject
+    Injector injector;
+
+    private InjectionPoint constructorInjectionPoint;
+    private Set<Dependency<?>> dependencies;
+
+    public AbstractInjectionProvider(Key<T> key) {
+        this.key = key;
+        constructorInjectionPoint = InjectionPoint.forConstructorOf(key.getTypeLiteral());
+
+        ImmutableSet.Builder<Dependency<?>> dependencyBuilder = ImmutableSet.builder();
+        dependencyBuilder.addAll(constructorInjectionPoint.getDependencies());
+        for (InjectionPoint injectionPoint : InjectionPoint.forInstanceMethodsAndFields(key.getTypeLiteral())) {
+            dependencyBuilder.addAll(injectionPoint.getDependencies());
+        }
+        this.dependencies = dependencyBuilder.build();
+    }
+
+    public T get() {
+        Constructor<T> constructor = getConstructor();
+        Object[] params = new Object[constructor.getParameterTypes().length];
+        for (Dependency<?> dependency : constructorInjectionPoint.getDependencies()) {
+            params[dependency.getParameterIndex()] = injector.getInstance(dependency.getKey());
+        }
+        T t;
+        try {
+            t = constructor.newInstance(params);
+        } catch (Exception e) {
+            throw new ProvisionException("Could not instantiate " + key + "", e);
+        }
+        injector.injectMembers(t);
+        return postProcess(t);
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private Constructor<T> getConstructor() {
+        return (Constructor<T>) constructorInjectionPoint.getMember();
+    }
+
+    protected T postProcess(T t) {
+        // do nothing by default
+        return t;
+    }
+
+    public Set<Dependency<?>> getDependencies() {
+        return dependencies;
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/FilterChainResolverProvider.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/FilterChainResolverProvider.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/FilterChainResolverProvider.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/FilterChainResolverProvider.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.web;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.ProviderWithDependencies;
+import org.apache.shiro.util.AntPathMatcher;
+import org.apache.shiro.util.PatternMatcher;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+
+import javax.servlet.Filter;
+import java.util.Map;
+import java.util.Set;
+
+@Singleton
+class FilterChainResolverProvider implements ProviderWithDependencies<FilterChainResolver> {
+    @Inject
+    Injector injector;
+
+    private final Map<String, Key<? extends Filter>[]> chains;
+
+    private final Set<Dependency<?>> dependencies;
+
+    private PatternMatcher patternMatcher = new AntPathMatcher();
+
+    public FilterChainResolverProvider(Map<String, Key<? extends Filter>[]> chains) {
+        this.chains = chains;
+        ImmutableSet.Builder<Dependency<?>> dependenciesBuilder = ImmutableSet.builder();
+        for (String chain : chains.keySet()) {
+            for (Key<? extends Filter> filterKey : chains.get(chain)) {
+                dependenciesBuilder.add(Dependency.get(filterKey));
+            }
+        }
+        this.dependencies = dependenciesBuilder.build();
+    }
+
+    @Inject(optional = true)
+    public void setPatternMatcher(PatternMatcher patternMatcher) {
+        this.patternMatcher = patternMatcher;
+    }
+
+    public Set<Dependency<?>> getDependencies() {
+        return dependencies;
+    }
+
+    public FilterChainResolver get() {
+        return new SimpleFilterChainResolver(chains, injector, patternMatcher);
+    }
+
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/GuiceShiroFilter.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/GuiceShiroFilter.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/GuiceShiroFilter.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/GuiceShiroFilter.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.web;
+
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.mgt.WebSecurityManager;
+import org.apache.shiro.web.servlet.AbstractShiroFilter;
+
+import javax.inject.Inject;
+
+/**
+ * Shiro filter that is managed by and receives its filter chain configurations from Guice.  The convenience method to
+ * map this filter to your application is
+ * {@link ShiroWebModule#bindGuiceFilter(com.google.inject.Binder) bindGuiceFilter}.
+ */
+public class GuiceShiroFilter extends AbstractShiroFilter {
+    @Inject
+    GuiceShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver filterChainResolver) {
+        this.setSecurityManager(webSecurityManager);
+        this.setFilterChainResolver(filterChainResolver);
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/PathMatchingFilterProvider.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/PathMatchingFilterProvider.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/PathMatchingFilterProvider.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/PathMatchingFilterProvider.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.web;
+
+import com.google.inject.Key;
+import org.apache.shiro.web.filter.PathMatchingFilter;
+
+import java.util.Map;
+
+class PathMatchingFilterProvider<T extends PathMatchingFilter> extends AbstractInjectionProvider<T> {
+    private Map<String, String> pathConfigs;
+
+    public PathMatchingFilterProvider(Key<T> key, Map<String, String> pathConfigs) {
+        super(key);
+        this.pathConfigs = pathConfigs;
+    }
+
+    @Override
+    protected T postProcess(T filter) {
+        for (Map.Entry<String, String> pathConfig : this.pathConfigs.entrySet()) {
+            filter.processPathConfig(pathConfig.getKey(), pathConfig.getValue());
+        }
+        return filter;
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/ShiroWebModule.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/ShiroWebModule.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/ShiroWebModule.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/ShiroWebModule.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.web;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import com.google.inject.Binder;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.AnnotatedBindingBuilder;
+import com.google.inject.name.Names;
+import com.google.inject.servlet.ServletModule;
+import org.apache.shiro.guice.ShiroModule;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.env.Environment;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.web.env.WebEnvironment;
+import org.apache.shiro.web.filter.PathMatchingFilter;
+import org.apache.shiro.web.filter.authc.*;
+import org.apache.shiro.web.filter.authz.*;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.filter.session.NoSessionCreationFilter;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.apache.shiro.web.mgt.WebSecurityManager;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+
+import javax.servlet.Filter;
+import javax.servlet.ServletContext;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Sets up Shiro lifecycles within Guice, enables the injecting of Shiro objects, and binds a default
+ * {@link org.apache.shiro.web.mgt.WebSecurityManager}, {@link org.apache.shiro.mgt.SecurityManager} and {@link org.apache.shiro.session.mgt.SessionManager}.  At least one realm must be added by
+ * using {@link #bindRealm() bindRealm}.
+ * <p/>
+ * Also provides for the configuring of filter chains and binds a {@link org.apache.shiro.web.filter.mgt.FilterChainResolver} with that information.
+ */
+public abstract class ShiroWebModule extends ShiroModule {
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<AnonymousFilter> ANON = Key.get(AnonymousFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<FormAuthenticationFilter> AUTHC = Key.get(FormAuthenticationFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<BasicHttpAuthenticationFilter> AUTHC_BASIC = Key.get(BasicHttpAuthenticationFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<NoSessionCreationFilter> NO_SESSION_CREATION = Key.get(NoSessionCreationFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<LogoutFilter> LOGOUT = Key.get(LogoutFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<PermissionsAuthorizationFilter> PERMS = Key.get(PermissionsAuthorizationFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<PortFilter> PORT = Key.get(PortFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<HttpMethodPermissionFilter> REST = Key.get(HttpMethodPermissionFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<RolesAuthorizationFilter> ROLES = Key.get(RolesAuthorizationFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<SslFilter> SSL = Key.get(SslFilter.class);
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static final Key<UserFilter> USER = Key.get(UserFilter.class);
+
+
+    static final String NAME = "SHIRO";
+
+    /**
+     * We use a LinkedHashMap here to ensure that iterator order is the same as add order.  This is important, as the
+     * FilterChainResolver uses iterator order when searching for a matching chain.
+     */
+    private final Map<String, Key<? extends Filter>[]> filterChains = new LinkedHashMap<String, Key<? extends Filter>[]>();
+    private final ServletContext servletContext;
+
+    public ShiroWebModule(ServletContext servletContext) {
+        this.servletContext = servletContext;
+    }
+
+    public static void bindGuiceFilter(Binder binder) {
+        binder.install(guiceFilterModule());
+    }
+
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static void bindGuiceFilter(final String pattern, Binder binder) {
+        binder.install(guiceFilterModule(pattern));
+    }
+
+    public static ServletModule guiceFilterModule() {
+        return guiceFilterModule("/*");
+    }
+
+    public static ServletModule guiceFilterModule(final String pattern) {
+        return new ServletModule() {
+            @Override
+            protected void configureServlets() {
+                filter(pattern).through(GuiceShiroFilter.class);
+            }
+        };
+    }
+
+    @Override
+    protected final void configureShiro() {
+        bind(Key.get(ServletContext.class, Names.named(NAME))).toInstance(this.servletContext);
+        bindWebSecurityManager(bind(WebSecurityManager.class));
+        bindWebEnvironment(bind(WebEnvironment.class));
+        bind(GuiceShiroFilter.class).asEagerSingleton();
+        expose(GuiceShiroFilter.class);
+
+        this.configureShiroWeb();
+
+        setupFilterChainConfigs();
+
+        bind(FilterChainResolver.class).toProvider(new FilterChainResolverProvider(filterChains));
+    }
+
+    private void setupFilterChainConfigs() {
+        Table<Key<? extends PathMatchingFilter>, String, String> configs = HashBasedTable.create();
+
+        for (Map.Entry<String, Key<? extends Filter>[]> filterChain : filterChains.entrySet()) {
+            for (int i = 0; i < filterChain.getValue().length; i++) {
+                Key<? extends Filter> key = filterChain.getValue()[i];
+                if (key instanceof FilterConfigKey) {
+                    FilterConfigKey<? extends PathMatchingFilter> configKey = (FilterConfigKey<? extends PathMatchingFilter>) key;
+                    key = configKey.getKey();
+                    filterChain.getValue()[i] = key;
+                    if (!PathMatchingFilter.class.isAssignableFrom(key.getTypeLiteral().getRawType())) {
+                        throw new ConfigurationException("Config information requires a PathMatchingFilter - can't apply to " + key.getTypeLiteral().getRawType());
+                    }
+                    configs.put(castToPathMatching(key), filterChain.getKey(), configKey.getConfigValue());
+                } else if (PathMatchingFilter.class.isAssignableFrom(key.getTypeLiteral().getRawType())) {
+                    configs.put(castToPathMatching(key), filterChain.getKey(), "");
+                }
+            }
+        }
+        for (Key<? extends PathMatchingFilter> filterKey : configs.rowKeySet()) {
+            bindPathMatchingFilter(filterKey, configs.row(filterKey));
+        }
+    }
+
+    private <T extends PathMatchingFilter> void bindPathMatchingFilter(Key<T> filterKey, Map<String, String> configs) {
+        bind(filterKey).toProvider(new PathMatchingFilterProvider<T>(filterKey, configs)).asEagerSingleton();
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private Key<? extends PathMatchingFilter> castToPathMatching(Key<? extends Filter> key) {
+        return (Key<? extends PathMatchingFilter>) key;
+    }
+
+    protected abstract void configureShiroWeb();
+
+    @SuppressWarnings({"unchecked"})
+    @Override
+    protected final void bindSecurityManager(AnnotatedBindingBuilder<? super SecurityManager> bind) {
+        bindWebSecurityManager(bind);
+    }
+
+    /**
+     * Binds the security manager.  Override this method in order to provide your own security manager binding.
+     * <p/>
+     * By default, a {@link org.apache.shiro.web.mgt.DefaultWebSecurityManager} is bound as an eager singleton.
+     *
+     * @param bind
+     */
+    protected void bindWebSecurityManager(AnnotatedBindingBuilder<? super WebSecurityManager> bind) {
+        try {
+            bind.toConstructor(DefaultWebSecurityManager.class.getConstructor(Collection.class)).asEagerSingleton();
+        } catch (NoSuchMethodException e) {
+            throw new ConfigurationException("This really shouldn't happen.  Either something has changed in Shiro, or there's a bug in ShiroModule.", e);
+        }
+    }
+
+    /**
+     * Binds the session manager.  Override this method in order to provide your own session manager binding.
+     * <p/>
+     * By default, a {@link org.apache.shiro.web.session.mgt.DefaultWebSessionManager} is bound as an eager singleton.
+     *
+     * @param bind
+     */
+    @Override
+    protected void bindSessionManager(AnnotatedBindingBuilder<SessionManager> bind) {
+        bind.to(DefaultWebSessionManager.class).asEagerSingleton();
+    }
+
+    @Override
+    protected final void bindEnvironment(AnnotatedBindingBuilder<Environment> bind) {
+        bindWebEnvironment(bind);
+    }
+
+    protected void bindWebEnvironment(AnnotatedBindingBuilder<? super WebEnvironment> bind) {
+        bind.to(WebGuiceEnvironment.class).asEagerSingleton();
+    }
+
+    /**
+     * Adds a filter chain to the shiro configuration.
+     * <p/>
+     * NOTE: If the provided key is for a subclass of {@link org.apache.shiro.web.filter.PathMatchingFilter}, it will be registered with a proper
+     * provider.
+     *
+     * @param pattern
+     * @param keys
+     */
+    @SuppressWarnings({"UnusedDeclaration"})
+    protected final void addFilterChain(String pattern, Key<? extends Filter>... keys) {
+        filterChains.put(pattern, keys);
+    }
+
+    protected static <T extends PathMatchingFilter> Key<T> config(Key<T> baseKey, String configValue) {
+        return new FilterConfigKey<T>(baseKey, configValue);
+    }
+
+    @SuppressWarnings({"UnusedDeclaration"})
+    protected static <T extends PathMatchingFilter> Key<T> config(TypeLiteral<T> typeLiteral, String configValue) {
+        return config(Key.get(typeLiteral), configValue);
+    }
+
+    @SuppressWarnings({"UnusedDeclaration"})
+    protected static <T extends PathMatchingFilter> Key<T> config(Class<T> type, String configValue) {
+        return config(Key.get(type), configValue);
+    }
+
+    private static class FilterConfigKey<T extends PathMatchingFilter> extends Key<T> {
+        private Key<T> key;
+        private String configValue;
+
+        private FilterConfigKey(Key<T> key, String configValue) {
+            super();
+            this.key = key;
+            this.configValue = configValue;
+        }
+
+        public Key<T> getKey() {
+            return key;
+        }
+
+        public String getConfigValue() {
+            return configValue;
+        }
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChain.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChain.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChain.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChain.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.web;
+
+import javax.servlet.*;
+import java.io.IOException;
+import java.util.Iterator;
+
+class SimpleFilterChain implements FilterChain {
+
+
+    private final FilterChain originalChain;
+    private final Iterator<? extends Filter> chain;
+
+    private boolean originalCalled = false;
+
+    public SimpleFilterChain(FilterChain originalChain, Iterator<? extends Filter> chain) {
+        this.originalChain = originalChain;
+        this.chain = chain;
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
+        if (chain.hasNext()) {
+            Filter filter = chain.next();
+            filter.doFilter(request, response, this);
+        } else if (!originalCalled) {
+            originalCalled = true;
+            originalChain.doFilter(request, response);
+        }
+    }
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChainResolver.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChainResolver.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChainResolver.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/SimpleFilterChainResolver.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.web;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterators;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import org.apache.shiro.util.PatternMatcher;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.util.WebUtils;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.util.Map;
+
+class SimpleFilterChainResolver implements FilterChainResolver {
+    private final Map<String, Key<? extends Filter>[]> chains;
+    private final Injector injector;
+    private final PatternMatcher patternMatcher;
+
+    SimpleFilterChainResolver(Map<String, Key<? extends Filter>[]> chains, Injector injector, PatternMatcher patternMatcher) {
+        this.chains = chains;
+        this.injector = injector;
+        this.patternMatcher = patternMatcher;
+    }
+
+    public FilterChain getChain(ServletRequest request, ServletResponse response, final FilterChain originalChain) {
+        String path = WebUtils.getPathWithinApplication(WebUtils.toHttp(request));
+        for (final String pathPattern : chains.keySet()) {
+            if (patternMatcher.matches(pathPattern, path)) {
+                return new SimpleFilterChain(originalChain, Iterators.transform(Iterators.forArray(chains.get(pathPattern)),
+                        new Function<Key<? extends Filter>, Filter>() {
+                            public Filter apply(Key<? extends Filter> input) {
+                                return injector.getInstance(input);
+                            }
+                        }));
+            }
+        }
+        return null;
+    }
+
+}

Added: shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/WebGuiceEnvironment.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/WebGuiceEnvironment.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/WebGuiceEnvironment.java (added)
+++ shiro/trunk/support/guice/src/main/java/org/apache/shiro/guice/web/WebGuiceEnvironment.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice.web;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.web.env.EnvironmentLoaderListener;
+import org.apache.shiro.web.env.WebEnvironment;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.mgt.WebSecurityManager;
+
+import javax.inject.Named;
+import javax.servlet.ServletContext;
+
+@Singleton
+class WebGuiceEnvironment implements WebEnvironment {
+    private FilterChainResolver filterChainResolver;
+    private ServletContext servletContext;
+    private WebSecurityManager securityManager;
+
+    @Inject
+    WebGuiceEnvironment(FilterChainResolver filterChainResolver, @Named(ShiroWebModule.NAME) ServletContext servletContext, WebSecurityManager securityManager) {
+        this.filterChainResolver = filterChainResolver;
+        this.servletContext = servletContext;
+        this.securityManager = securityManager;
+
+        servletContext.setAttribute(EnvironmentLoaderListener.ENVIRONMENT_ATTRIBUTE_KEY, this);
+    }
+
+    public FilterChainResolver getFilterChainResolver() {
+        return filterChainResolver;
+    }
+
+    public ServletContext getServletContext() {
+        return servletContext;
+    }
+
+    public WebSecurityManager getWebSecurityManager() {
+        return securityManager;
+    }
+
+    public SecurityManager getSecurityManager() {
+        return securityManager;
+    }
+}

Added: shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/BeanTypeListenerTest.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/BeanTypeListenerTest.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/BeanTypeListenerTest.java (added)
+++ shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/BeanTypeListenerTest.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import com.google.inject.*;
+import com.google.inject.name.Names;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.TypeEncounter;
+import org.apache.shiro.guice.aop.ShiroAopModule;
+import org.apache.shiro.guice.web.ShiroWebModule;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.aop.DefaultAnnotationResolver;
+import org.apache.shiro.crypto.BlowfishCipherService;
+import org.easymock.Capture;
+import org.easymock.IMocksControl;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+/**
+ * Test Cases::
+ * Test package matching
+ * injects on classes in shiro package and sub packages
+ * excludes classes in shiro-guice package and sub packages
+ * Test that properties are set properly
+ * ensure optional
+ * ensure property names are correct
+ * ensure "named" properties require a name, and unnamed do not
+ */
+public class BeanTypeListenerTest {
+    @Test
+    public void testUnmatchedPackage() throws Exception {
+        assertFalse(BeanTypeListener.MATCHER.matches(TypeLiteral.get(GuiceEnvironment.class)));
+        assertFalse(BeanTypeListener.MATCHER.matches(TypeLiteral.get(ShiroWebModule.class)));
+        assertFalse(BeanTypeListener.MATCHER.matches(TypeLiteral.get(ShiroAopModule.class)));
+    }
+
+    @Test
+    public void testMatchedPackage() throws Exception {
+        assertTrue(BeanTypeListener.MATCHER.matches(TypeLiteral.get(SecurityUtils.class)));
+        assertTrue(BeanTypeListener.MATCHER.matches(TypeLiteral.get(DefaultAnnotationResolver.class)));
+        assertTrue(BeanTypeListener.MATCHER.matches(TypeLiteral.get(BlowfishCipherService.class)));
+    }
+
+    @Test
+    public void testPropertySetting() throws Exception {
+        IMocksControl control = createControl();
+        TypeEncounter<SomeInjectableBean> encounter = control.createMock(TypeEncounter.class);
+
+        Provider<Injector> injectorProvider = control.createMock(Provider.class);
+        Injector injector = control.createMock(Injector.class);
+
+        expect(encounter.getProvider(Injector.class)).andReturn(injectorProvider);
+
+        expect(injectorProvider.get()).andReturn(injector).anyTimes();
+
+        Capture<MembersInjector<SomeInjectableBean>> capture = new Capture<MembersInjector<SomeInjectableBean>>();
+        encounter.register(and(anyObject(MembersInjector.class), capture(capture)));
+
+        SecurityManager securityManager = control.createMock(SecurityManager.class);
+        String property = "myPropertyValue";
+
+        expect(injector.getInstance(Key.get(SecurityManager.class))).andReturn(securityManager);
+        expect(injector.getInstance(Key.get(String.class, Names.named("shiro.myProperty")))).andReturn(property);
+        expect(injector.getInstance(Key.get(String.class, Names.named("shiro.unavailableProperty"))))
+                .andThrow(new ConfigurationException(Collections.singleton(new Message("Not Available!"))));
+
+        control.replay();
+
+        BeanTypeListener underTest = new BeanTypeListener();
+
+        underTest.hear(TypeLiteral.get(SomeInjectableBean.class), encounter);
+
+        SomeInjectableBean bean = new SomeInjectableBean();
+
+        capture.getValue().injectMembers(bean);
+
+        assertSame(securityManager, bean.securityManager);
+        assertSame(property, bean.myProperty);
+        assertNull(bean.unavailableProperty);
+
+        control.verify();
+    }
+
+    public static class SomeInjectableBean {
+        private SecurityManager securityManager;
+        private String myProperty;
+        private String unavailableProperty;
+
+        public void setSecurityManager(SecurityManager securityManager) {
+
+            this.securityManager = securityManager;
+        }
+
+        public void setMyProperty(String myProperty) {
+
+            this.myProperty = myProperty;
+        }
+
+        public void setUnavailableProperty(String unavailableProperty) {
+
+            this.unavailableProperty = unavailableProperty;
+        }
+    }
+}

Added: shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/DestroyableInjectionListenerTest.java
URL: http://svn.apache.org/viewvc/shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/DestroyableInjectionListenerTest.java?rev=1147810&view=auto
==============================================================================
--- shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/DestroyableInjectionListenerTest.java (added)
+++ shiro/trunk/support/guice/src/test/java/org/apache/shiro/guice/DestroyableInjectionListenerTest.java Mon Jul 18 11:10:51 2011
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shiro.guice;
+
+import org.apache.shiro.util.Destroyable;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+
+public class DestroyableInjectionListenerTest {
+    @Test
+    public void testAfterInjection() throws Exception {
+        DestroyableInjectionListener.DestroyableRegistry registry = createMock(DestroyableInjectionListener.DestroyableRegistry.class);
+        Destroyable destroyable = createMock(Destroyable.class);
+
+        registry.add(destroyable);
+
+        replay(registry, destroyable);
+
+        DestroyableInjectionListener underTest = new DestroyableInjectionListener(registry);
+        underTest.afterInjection(destroyable);
+
+        verify(registry, destroyable);
+    }
+}