You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by bd...@apache.org on 2017/01/17 20:56:02 UTC

[2/3] shiro git commit: Initial pass at CDI support (without requiring a shiro.ini file)

Initial pass at CDI support (without requiring a shiro.ini file)

Fixes: #24


Project: http://git-wip-us.apache.org/repos/asf/shiro/repo
Commit: http://git-wip-us.apache.org/repos/asf/shiro/commit/59b944c0
Tree: http://git-wip-us.apache.org/repos/asf/shiro/tree/59b944c0
Diff: http://git-wip-us.apache.org/repos/asf/shiro/diff/59b944c0

Branch: refs/heads/cdi-idea
Commit: 59b944c01f51adf9e9c94c4ce07469427c974ee8
Parents: 0aec373
Author: Brian Demers <bd...@apache.org>
Authored: Mon Nov 28 16:33:21 2016 -0500
Committer: Brian Demers <bd...@apache.org>
Committed: Tue Jan 17 15:46:37 2017 -0500

----------------------------------------------------------------------
 samples/cdi-core/pom.xml                        | 110 +++++++++
 .../apache/shiro/samples/cdi/CdiQuickStart.java | 107 +++++++++
 .../apache/shiro/samples/cdi/RealmProducer.java |  33 +++
 .../src/main/resources/META-INF/beans.xml       |   1 +
 samples/cdi-core/src/main/resources/logback.xml |  33 +++
 samples/cdi-core/src/main/resources/shiro.ini   |  58 +++++
 .../shiro/samples/cdi/CdiQuickStartIT.groovy    |  25 ++
 samples/cdi-web/pom.xml                         | 134 +++++++++++
 .../shiro/samples/jaxrs/SampleApplication.java  |  87 +++++++
 .../samples/jaxrs/resources/HelloResource.java  |  37 +++
 .../samples/jaxrs/resources/SecureResource.java |  75 ++++++
 .../samples/jaxrs/resources/WhoAmIResource.java |  55 +++++
 samples/cdi-web/src/main/resources/logback.xml  |  33 +++
 samples/cdi-web/src/main/resources/shiro.ini    |  43 ++++
 .../cdi-web/src/main/webapp/WEB-INF/beans.xml   |   1 +
 samples/cdi-web/src/main/webapp/WEB-INF/web.xml |  10 +
 .../web/jaxrs/ContainerIntegrationIT.groovy     | 134 +++++++++++
 samples/pom.xml                                 |   2 +
 support/cdi/cdi-base/pom.xml                    | 108 +++++++++
 .../org/apache/shiro/cdi/CdiEnvironment.java    |  36 +++
 .../EventListenerRegistrationInterceptor.java   |  74 ++++++
 .../shiro/cdi/ShiroAnnotationInterceptor.java   |  75 ++++++
 .../org/apache/shiro/cdi/ShiroCdiExtension.java | 191 ++++++++++++++++
 .../java/org/apache/shiro/cdi/Standard.java     |  17 ++
 .../AbstractSecurityManagerProducer.java        | 134 +++++++++++
 .../AuthenticationStrategyProducer.java         |  15 ++
 .../shiro/cdi/producers/EventBusProducer.java   |  16 ++
 .../cdi/producers/SessionFactoryProducer.java   |  15 ++
 .../SessionStorageEvaluatorProducer.java        |  14 ++
 .../shiro/cdi/producers/SubjectDaoProducer.java |  16 ++
 .../shiro/cdi/producers/SubjectProducer.java    |  21 ++
 .../src/main/resources/META-INF/beans.xml       |   7 +
 .../javax.enterprise.inject.spi.Extension       |   1 +
 .../org/apache/shiro/cdi/CdiHackingTest.groovy  | 112 +++++++++
 .../shiro/cdi/EventBusSubscribeTest.groovy      |  55 +++++
 .../cdi/ShiroAnnotationInterceptorsTest.groovy  | 228 +++++++++++++++++++
 .../apache/shiro/cdi/AnnotationTestStub.java    |  56 +++++
 .../org/apache/shiro/cdi/EventBusAwareStub.java |  41 ++++
 .../org/apache/shiro/cdi/EventListenerStub.java |  38 ++++
 .../org/apache/shiro/cdi/StubConfiguration.java |  40 ++++
 .../src/test/resources/META-INF/beans.xml       |   1 +
 support/cdi/cdi-core/pom.xml                    | 109 +++++++++
 .../core/producers/SecurityManagerProducer.java |  82 +++++++
 .../src/main/resources/META-INF/beans.xml       |   1 +
 .../org/apache/shiro/cdi/CdiHackingTest.groovy  | 108 +++++++++
 .../org/apache/shiro/cdi/StubConfiguration.java |  29 +++
 .../src/test/resources/META-INF/beans.xml       |   1 +
 support/cdi/cdi-web/pom.xml                     | 133 +++++++++++
 .../apache/shiro/cdi/web/CdiWebEnvironment.java |  43 ++++
 .../apache/shiro/cdi/web/NativeSessions.java    |  17 ++
 .../shiro/cdi/web/ServletContainerSessions.java |  17 ++
 .../main/java/org/apache/shiro/cdi/web/Web.java |  14 ++
 .../producers/WebSecurityManagerProducer.java   |  82 +++++++
 .../producers/WebSessionManagerProvider.java    |  25 ++
 .../src/main/resources/META-INF/beans.xml       |   1 +
 .../apache/shiro/cdi/web/MoreHackingTest.groovy |  82 +++++++
 .../apache/shiro/cdi/web/StubConfiguration.java |  18 ++
 .../src/test/resources/META-INF/beans.xml       |   1 +
 support/cdi/pom.xml                             |  46 ++++
 support/pom.xml                                 |   1 +
 60 files changed, 3099 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-core/pom.xml
----------------------------------------------------------------------
diff --git a/samples/cdi-core/pom.xml b/samples/cdi-core/pom.xml
new file mode 100644
index 0000000..b14f9db
--- /dev/null
+++ b/samples/cdi-core/pom.xml
@@ -0,0 +1,110 @@
+<?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.
+  -->
+<!--suppress osmorcNonOsgiMavenDependency -->
+<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.samples</groupId>
+        <artifactId>shiro-samples</artifactId>
+        <version>1.4.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>samples-cdi-core</artifactId>
+    <name>Apache Shiro :: Samples :: CDI Core</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <jdk.version>1.7</jdk.version>
+        <deltaspike.version>1.7.2</deltaspike.version>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>1.1</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>java</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <classpathScope>test</classpathScope>
+                    <mainClass>Quickstart</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-cdi-core</artifactId>
+            <version>1.4.0-SNAPSHOT</version>
+        </dependency>
+
+        <!-- configure logging -->
+        <!--<dependency>-->
+            <!--<groupId>org.slf4j</groupId>-->
+            <!--<artifactId>jcl-over-slf4j</artifactId>-->
+            <!--<scope>runtime</scope>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.deltaspike.modules</groupId>
+            <artifactId>deltaspike-test-control-module-api</artifactId>
+            <version>${deltaspike.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.deltaspike.modules</groupId>
+            <artifactId>deltaspike-test-control-module-impl</artifactId>
+            <version>${deltaspike.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.deltaspike.cdictrl</groupId>
+            <artifactId>deltaspike-cdictrl-weld</artifactId>
+            <version>${deltaspike.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.weld.se</groupId>
+            <artifactId>weld-se-core</artifactId>
+            <version>2.4.1.Final</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-core/src/main/java/org/apache/shiro/samples/cdi/CdiQuickStart.java
----------------------------------------------------------------------
diff --git a/samples/cdi-core/src/main/java/org/apache/shiro/samples/cdi/CdiQuickStart.java b/samples/cdi-core/src/main/java/org/apache/shiro/samples/cdi/CdiQuickStart.java
new file mode 100644
index 0000000..dbfa568
--- /dev/null
+++ b/samples/cdi-core/src/main/java/org/apache/shiro/samples/cdi/CdiQuickStart.java
@@ -0,0 +1,107 @@
+package org.apache.shiro.samples.cdi;
+
+
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.LockedAccountException;
+import org.apache.shiro.authc.UnknownAccountException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.realm.text.IniRealm;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.Initializable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.New;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.Typed;
+import javax.inject.Inject;
+
+import static com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type.Real;
+import static javafx.scene.input.KeyCode.R;
+
+@ApplicationScoped
+public class CdiQuickStart {
+
+    private static final transient Logger log = LoggerFactory.getLogger(CdiQuickStart.class);
+
+    @Inject
+    private SecurityManager securityManager;
+
+    public void runMe() {
+        // get the currently executing user:
+        Subject currentUser = new Subject.Builder(securityManager).buildSubject();
+
+        // Typically you would want to get access to the current threads's subject like this:
+        // Subject currentUser = SecurityUtils.getSubject();
+        // But that requires you to set the current Thread's SecurityManager (or a static instance)
+        // ThreadContext.bind() or SecurityUtils.setSecurityManager()
+        // For this example, we can just create a Subject directly
+
+        // Do some stuff with a Session (no need for a web or EJB container!!!)
+        Session session = currentUser.getSession();
+        session.setAttribute("someKey", "aValue");
+        String value = (String) session.getAttribute("someKey");
+        if (value.equals("aValue")) {
+            log.info("Retrieved the correct value! [" + value + "]");
+        }
+
+        // let's login the current user so we can check against roles and permissions:
+        if (!currentUser.isAuthenticated()) {
+            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
+            token.setRememberMe(true);
+            try {
+                currentUser.login(token);
+            } catch (UnknownAccountException uae) {
+                log.info("There is no user with username of " + token.getPrincipal());
+            } catch (IncorrectCredentialsException ice) {
+                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
+            } catch (LockedAccountException lae) {
+                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
+                        "Please contact your administrator to unlock it.");
+            }
+            // ... catch more exceptions here (maybe custom ones specific to your application?
+            catch (AuthenticationException ae) {
+                //unexpected condition?  error?
+                throw new ConfigurationException("Something is nog configured correctly", ae);
+            }
+        }
+
+        //say who they are:
+        //print their identifying principal (in this case, a username):
+        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
+
+        //test a role:
+        if (currentUser.hasRole("schwartz")) {
+            log.info("May the Schwartz be with you!");
+        } else {
+            log.info("Hello, mere mortal.");
+        }
+
+        //test a typed permission (not instance-level)
+        if (currentUser.isPermitted("lightsaber:weild")) {
+            log.info("You may use a lightsaber ring.  Use it wisely.");
+        } else {
+            log.info("Sorry, lightsaber rings are for schwartz masters only.");
+        }
+
+        //a (very powerful) Instance Level permission:
+        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
+            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
+                    "Here are the keys - have fun!");
+        } else {
+            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
+        }
+
+        //all done - log out!
+        currentUser.logout();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-core/src/main/java/org/apache/shiro/samples/cdi/RealmProducer.java
----------------------------------------------------------------------
diff --git a/samples/cdi-core/src/main/java/org/apache/shiro/samples/cdi/RealmProducer.java b/samples/cdi-core/src/main/java/org/apache/shiro/samples/cdi/RealmProducer.java
new file mode 100644
index 0000000..91bfd90
--- /dev/null
+++ b/samples/cdi-core/src/main/java/org/apache/shiro/samples/cdi/RealmProducer.java
@@ -0,0 +1,33 @@
+package org.apache.shiro.samples.cdi;
+
+
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.realm.text.IniRealm;
+import org.apache.shiro.util.Initializable;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.New;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.Typed;
+
+/**
+ *
+ */
+public class RealmProducer {
+
+    @Produces
+    @Typed({Realm.class, Initializable.class})
+    private IniRealm createIniRealm(@New IniRealm iniRealm) {
+        Ini ini = Ini.fromResourcePath("classpath:shiro.ini");
+        iniRealm.setIni(ini);
+        return iniRealm;
+    }
+
+//    @Produces
+//    @ApplicationScoped
+//    private Ini loadShiroIni() {
+//        return Ini.fromResourcePath("classpath:shiro.ini");
+//    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-core/src/main/resources/META-INF/beans.xml
----------------------------------------------------------------------
diff --git a/samples/cdi-core/src/main/resources/META-INF/beans.xml b/samples/cdi-core/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..330c7f6
--- /dev/null
+++ b/samples/cdi-core/src/main/resources/META-INF/beans.xml
@@ -0,0 +1 @@
+<beans/>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-core/src/main/resources/logback.xml
----------------------------------------------------------------------
diff --git a/samples/cdi-core/src/main/resources/logback.xml b/samples/cdi-core/src/main/resources/logback.xml
new file mode 100644
index 0000000..25c7077
--- /dev/null
+++ b/samples/cdi-core/src/main/resources/logback.xml
@@ -0,0 +1,33 @@
+<?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.
+  -->
+<configuration>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <root level="INFO">
+        <appender-ref ref="STDOUT" />
+    </root>
+
+    <logger name="org.apache.shiro.samples" level="DEBUG"/>
+</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-core/src/main/resources/shiro.ini
----------------------------------------------------------------------
diff --git a/samples/cdi-core/src/main/resources/shiro.ini b/samples/cdi-core/src/main/resources/shiro.ini
new file mode 100644
index 0000000..adca38c
--- /dev/null
+++ b/samples/cdi-core/src/main/resources/shiro.ini
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+# =============================================================================
+# Quickstart INI Realm configuration
+#
+# For those that might not understand the references in this file, the
+# definitions are all based on the classic Mel Brooks' film "Spaceballs". ;)
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# Users and their assigned roles
+#
+# Each line conforms to the format defined in the
+# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc
+# -----------------------------------------------------------------------------
+[users]
+# user 'root' with password 'secret' and the 'admin' role
+root = secret, admin
+# user 'guest' with the password 'guest' and the 'guest' role
+guest = guest, guest
+# user 'presidentskroob' with password '12345' ("That's the same combination on
+# my luggage!!!" ;)), and role 'president'
+presidentskroob = 12345, president
+# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
+darkhelmet = ludicrousspeed, darklord, schwartz
+# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
+lonestarr = vespa, goodguy, schwartz
+
+# -----------------------------------------------------------------------------
+# Roles with assigned permissions
+# 
+# Each line conforms to the format defined in the
+# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
+# -----------------------------------------------------------------------------
+[roles]
+# 'admin' role has all permissions, indicated by the wildcard '*'
+admin = *
+# The 'schwartz' role can do anything (*) with any lightsaber:
+schwartz = lightsaber:*
+# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
+# license plate 'eagle5' (instance specific id)
+goodguy = winnebago:drive:eagle5

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-core/src/test/groovy/org/apache/shiro/samples/cdi/CdiQuickStartIT.groovy
----------------------------------------------------------------------
diff --git a/samples/cdi-core/src/test/groovy/org/apache/shiro/samples/cdi/CdiQuickStartIT.groovy b/samples/cdi-core/src/test/groovy/org/apache/shiro/samples/cdi/CdiQuickStartIT.groovy
new file mode 100644
index 0000000..11dadb5
--- /dev/null
+++ b/samples/cdi-core/src/test/groovy/org/apache/shiro/samples/cdi/CdiQuickStartIT.groovy
@@ -0,0 +1,25 @@
+package org.apache.shiro.samples.cdi
+
+import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import javax.inject.Inject
+
+/**
+ * Simple Test for {@link CdiQuickStart}.
+ */
+@RunWith(CdiTestRunner)
+class CdiQuickStartIT {
+
+    @Inject
+    CdiQuickStart cdiQuickStart;
+
+    @Test
+    void runQuickStart() {
+
+        println("WTF")
+
+        cdiQuickStart.runMe()
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/pom.xml
----------------------------------------------------------------------
diff --git a/samples/cdi-web/pom.xml b/samples/cdi-web/pom.xml
new file mode 100644
index 0000000..050ecac
--- /dev/null
+++ b/samples/cdi-web/pom.xml
@@ -0,0 +1,134 @@
+<?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.
+  -->
+<!--suppress osmorcNonOsgiMavenDependency -->
+<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.samples</groupId>
+        <artifactId>shiro-samples</artifactId>
+        <version>1.4.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>samples-cdi-web</artifactId>
+    <name>Apache Shiro :: Samples :: CDI Web</name>
+    <packaging>war</packaging>
+
+    <properties>
+
+        <maven.compiler.target>1.7</maven.compiler.target>
+        <maven.compiler.source>1.7</maven.compiler.source>
+
+        <tomee.version>7.0.2</tomee.version>
+        <tomee.classifier>plus</tomee.classifier>
+
+        <jdk.version>1.7</jdk.version>
+        <deltaspike.version>1.7.2</deltaspike.version>
+
+        <jersey.version>2.23.2</jersey.version>
+        <mainClass>org.apache.shiro.samples.jaxrs.SampleApplication</mainClass>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>org.apache.shiro.samples.jaxrs.SampleApplication</mainClass>
+                    <classpathScope>test</classpathScope>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.tomee.maven</groupId>
+                <artifactId>tomee-maven-plugin</artifactId>
+                <version>${tomee.version}</version>
+                <configuration>
+                    <tomeeVersion>${tomee.version}</tomeeVersion>
+                    <tomeeClassifier>${tomee.classifier}</tomeeClassifier>
+                </configuration>
+            </plugin>
+
+        </plugins>
+    </build>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-servlet-plugin</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-cdi-web</artifactId>
+            <version>1.4.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-jaxrs</artifactId>
+        </dependency>
+
+        <dependency>
+            <!-- Required for any libraries that expect to call the commons logging APIs -->
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+
+
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+            <version>2.0.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>1.3</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <version>1.2</version>
+            <scope>provided</scope>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.apache.openwebbeans</groupId>
+            <artifactId>openwebbeans-impl</artifactId>
+            <version>1.7.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/SampleApplication.java
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/SampleApplication.java b/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/SampleApplication.java
new file mode 100644
index 0000000..a13c885
--- /dev/null
+++ b/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/SampleApplication.java
@@ -0,0 +1,87 @@
+/*
+ * 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.samples.jaxrs;
+
+import org.apache.shiro.samples.jaxrs.resources.HelloResource;
+import org.apache.shiro.samples.jaxrs.resources.SecureResource;
+import org.apache.shiro.samples.jaxrs.resources.WhoAmIResource;
+import org.apache.shiro.web.jaxrs.ShiroFeature;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Simple JAX-RS {@link Application} that is implementation agnostic.
+ * @since 1.4
+ */
+@ApplicationPath("/")
+public class SampleApplication extends Application {
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        Set<Class<?>> classes = new HashSet<Class<?>>();
+
+        // register Shiro
+        classes.add(ShiroFeature.class);
+
+        // register resources
+        classes.add(HelloResource.class);
+        classes.add(SecureResource.class);
+        classes.add(WhoAmIResource.class);
+
+        return classes;
+    }
+
+
+//    private static final URI BASE_URI = URI.create("http://localhost:8080/");
+//
+//    public static void main(String[] args) {
+//        try {
+//            System.out.println("Jersey CDI Example App");
+//
+//            final Weld weld = new Weld();
+//            weld.initialize();
+//
+//            final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, createJaxRsApp(), false);
+//            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+//                @Override
+//                public void run() {
+//                    server.shutdownNow();
+//                    weld.shutdown();
+//                }
+//            }));
+//            server.start();
+//
+//            System.out.println(String.format("Application started.\nTry out %s%s\nStop the application using CTRL+C",
+//                    BASE_URI, "application.wadl"));
+//
+//            Thread.currentThread().join();
+//        } catch (IOException | InterruptedException ex) {
+//            LoggerFactory.getLogger(SampleApplication.class).error(null, ex);
+//        }
+//
+//    }
+//
+//    private static ResourceConfig createJaxRsApp() {
+//        return ResourceConfig.forApplicationClass(SampleApplication.class);
+//    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/HelloResource.java
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/HelloResource.java b/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/HelloResource.java
new file mode 100644
index 0000000..400f503
--- /dev/null
+++ b/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/HelloResource.java
@@ -0,0 +1,37 @@
+/*
+ * 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.samples.jaxrs.resources;
+
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+@Path("say")
+public class HelloResource {
+
+
+    @Produces({"application/json","plain/text"})
+    @GET
+    public String saySomething(@QueryParam("words") @DefaultValue("Hello!") String words) {
+        return words;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/SecureResource.java
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/SecureResource.java b/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/SecureResource.java
new file mode 100644
index 0000000..c590987
--- /dev/null
+++ b/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/SecureResource.java
@@ -0,0 +1,75 @@
+/*
+ * 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.samples.jaxrs.resources;
+
+
+import org.apache.shiro.authz.annotation.RequiresAuthentication;
+import org.apache.shiro.authz.annotation.RequiresGuest;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.apache.shiro.authz.annotation.RequiresRoles;
+import org.apache.shiro.authz.annotation.RequiresUser;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+@Path("secure")
+@Produces({"application/json","plain/text"})
+public class SecureResource {
+
+
+    @RequiresPermissions("lightsaber:requiresPermissions")
+    @Path("RequiresPermissions")
+    @GET
+    public String protectedByRequiresPermissions() {
+        return "protected";
+    }
+
+    @RequiresRoles("admin")
+    @Path("RequiresRoles")
+    @GET
+    public String protectedByRequiresRoles() {
+        return "protected";
+    }
+
+    @RequiresUser
+    @Path("RequiresUser")
+    @GET
+    public String protectedByRequiresUser() {
+        return "protected";
+    }
+
+    @RequiresGuest
+    @Path("RequiresGuest")
+    @GET
+    public String protectedByRequiresGuest() {
+        return "not protected";
+    }
+
+    @RequiresAuthentication
+    @Path("RequiresAuthentication")
+    @GET
+    public String protectedByRequiresAuthentication() {
+        return "protected";
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/WhoAmIResource.java
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/WhoAmIResource.java b/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/WhoAmIResource.java
new file mode 100644
index 0000000..337e706
--- /dev/null
+++ b/samples/cdi-web/src/main/java/org/apache/shiro/samples/jaxrs/resources/WhoAmIResource.java
@@ -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.samples.jaxrs.resources;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.cdi.web.Web;
+import org.apache.shiro.subject.Subject;
+
+import javax.annotation.ManagedBean;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+@Path("whoami")
+@Produces({"application/json","plain/text"})
+//@RequestScoped
+//@ApplicationScoped
+//@ManagedBean
+public class WhoAmIResource {
+
+    @Inject
+    private Subject subject;
+
+    @GET
+    public String whoAmI() {
+
+//        Subject subject = SecurityUtils.getSubject();
+
+        Object principal = subject.getPrincipal();
+
+        if (principal == null) {
+            principal = "guest";
+        }
+
+        return principal.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/main/resources/logback.xml
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/main/resources/logback.xml b/samples/cdi-web/src/main/resources/logback.xml
new file mode 100644
index 0000000..283b72d
--- /dev/null
+++ b/samples/cdi-web/src/main/resources/logback.xml
@@ -0,0 +1,33 @@
+<?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.
+  -->
+<configuration>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <root level="DEBUG">
+        <appender-ref ref="STDOUT" />
+    </root>
+
+    <logger name="org.apache.shiro" level="DEBUG"/>
+</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/main/resources/shiro.ini
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/main/resources/shiro.ini b/samples/cdi-web/src/main/resources/shiro.ini
new file mode 100644
index 0000000..54fa949
--- /dev/null
+++ b/samples/cdi-web/src/main/resources/shiro.ini
@@ -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.
+
+[main]
+cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
+
+sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
+sessionManager.sessionIdUrlRewritingEnabled = false
+
+securityManager.sessionManager = $sessionManager
+securityManager.cacheManager = $cacheManager
+
+[urls]
+/** = authcBasic[permissive]
+
+[users]
+# format: username = password, role1, role2, ..., roleN
+root = secret,admin
+guest = guest,guest
+presidentskroob = 12345,president
+darkhelmet = ludicrousspeed,darklord,schwartz
+lonestarr = vespa,goodguy,schwartz
+
+[roles]
+# format: roleName = permission1, permission2, ..., permissionN
+admin = *
+schwartz = lightsaber:*
+goodguy = winnebago:drive:eagle5

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/main/webapp/WEB-INF/beans.xml
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/main/webapp/WEB-INF/beans.xml b/samples/cdi-web/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..330c7f6
--- /dev/null
+++ b/samples/cdi-web/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1 @@
+<beans/>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/main/webapp/WEB-INF/web.xml b/samples/cdi-web/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..852ba1f
--- /dev/null
+++ b/samples/cdi-web/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,10 @@
+<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+         version="3.1">
+
+    <display-name>test</display-name>
+
+
+
+</web-app>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/cdi-web/src/test/groovy/org/apache/shiro/web/jaxrs/ContainerIntegrationIT.groovy
----------------------------------------------------------------------
diff --git a/samples/cdi-web/src/test/groovy/org/apache/shiro/web/jaxrs/ContainerIntegrationIT.groovy b/samples/cdi-web/src/test/groovy/org/apache/shiro/web/jaxrs/ContainerIntegrationIT.groovy
new file mode 100644
index 0000000..4dd84cc
--- /dev/null
+++ b/samples/cdi-web/src/test/groovy/org/apache/shiro/web/jaxrs/ContainerIntegrationIT.groovy
@@ -0,0 +1,134 @@
+/*
+ * 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.web.jaxrs
+
+//import org.apache.shiro.testing.web.AbstractContainerIT
+//import org.junit.Test;
+//
+//import static com.jayway.restassured.RestAssured.*
+//import static org.hamcrest.Matchers.*
+
+public class ContainerIntegrationIT {
+//        extends AbstractContainerIT {
+
+//    @Test
+//    void testNoAuthResource() {
+//
+//        get(getBaseUri() + "say")
+//            .then()
+//                .assertThat()
+//                .statusCode(is(200)).and()
+//                .body(equalTo("Hello!"))
+//    }
+//
+//    @Test
+//    void testSecuredRequiresAuthentication() {
+//
+//        get(getBaseUri() + "secure/RequiresAuthentication")
+//            .then()
+//                .assertThat().statusCode(is(401))
+//
+//        given()
+//            .header("Authorization", getBasicAuthorizationHeaderValue("root", "secret"))
+//        .when()
+//            .get(getBaseUri() + "secure/RequiresAuthentication")
+//        .then()
+//            .assertThat()
+//                .statusCode(is(200)).and()
+//                .body(equalTo("protected"))
+//    }
+//
+//    @Test
+//    void testSecuredRequiresUser() {
+//
+//        get(getBaseUri() + "secure/RequiresUser")
+//            .then()
+//                .assertThat().statusCode(is(401))
+//
+//        given()
+//            .header("Authorization", getBasicAuthorizationHeaderValue("root", "secret"))
+//        .when()
+//            .get(getBaseUri() + "secure/RequiresUser")
+//        .then()
+//            .assertThat()
+//                .statusCode(is(200)).and()
+//                .body(equalTo("protected"))
+//    }
+//
+//    @Test
+//    void testSecuredRequiresRoles() {
+//
+//        get(getBaseUri() + "secure/RequiresRoles")
+//            .then()
+//                .assertThat().statusCode(is(401))
+//
+//        given()
+//                .header("Authorization", getBasicAuthorizationHeaderValue("guest", "guest"))
+//        .when()
+//            .get(getBaseUri() + "secure/RequiresRoles")
+//        .then()
+//            .assertThat()
+//                .statusCode(is(403)).and()
+//
+//        given()
+//            .header("Authorization", getBasicAuthorizationHeaderValue("root", "secret"))
+//        .when()
+//            .get(getBaseUri() + "secure/RequiresRoles")
+//        .then()
+//            .assertThat()
+//                .statusCode(is(200)).and()
+//                .body(equalTo("protected"))
+//    }
+//
+//    @Test
+//    void testSecuredRequiresPermissions() {
+//
+//        get(getBaseUri() + "secure/RequiresPermissions")
+//            .then()
+//                .assertThat().statusCode(is(401))
+//
+//        given()
+//            .header("Authorization", getBasicAuthorizationHeaderValue("guest", "guest"))
+//        .when()
+//            .get(getBaseUri() + "secure/RequiresPermissions")
+//        .then()
+//            .assertThat()
+//                .statusCode(is(403)).and()
+//
+//        given()
+//            .header("Authorization", getBasicAuthorizationHeaderValue("lonestarr", "vespa"))
+//        .when()
+//            .get(getBaseUri() + "secure/RequiresPermissions")
+//        .then()
+//            .assertThat()
+//                .statusCode(is(200)).and()
+//                .body(equalTo("protected"))
+//    }
+//
+//    @Test
+//    void testSecuredRequiresGuest() {
+//
+//        get(getBaseUri() + "secure/RequiresGuest")
+//            .then()
+//                .assertThat()
+//                    .statusCode(is(200)).and()
+//                    .body(equalTo("not protected"))
+//    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/samples/pom.xml
----------------------------------------------------------------------
diff --git a/samples/pom.xml b/samples/pom.xml
index 72b9193..bb232e2 100644
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -47,6 +47,8 @@
         <module>quickstart-guice</module>
         <module>servlet-plugin</module>
         <module>jaxrs</module>
+        <module>cdi-core</module>
+        <module>cdi-web</module>
     </modules>
 
     <reporting>

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/pom.xml
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/pom.xml b/support/cdi/cdi-base/pom.xml
new file mode 100644
index 0000000..f21deb2
--- /dev/null
+++ b/support/cdi/cdi-base/pom.xml
@@ -0,0 +1,108 @@
+<?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-cdi</artifactId>
+        <version>1.4.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>shiro-cdi-base</artifactId>
+    <name>Apache Shiro :: Support :: CDI Base</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+
+        <dependency>
+        <groupId>org.apache.shiro</groupId>
+        <artifactId>shiro-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <version>1.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>1.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.deltaspike.modules</groupId>
+            <artifactId>deltaspike-test-control-module-api</artifactId>
+            <version>${deltaspike.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.deltaspike.modules</groupId>
+            <artifactId>deltaspike-test-control-module-impl</artifactId>
+            <version>${deltaspike.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.deltaspike.cdictrl</groupId>
+            <artifactId>deltaspike-cdictrl-weld</artifactId>
+            <version>${deltaspike.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.weld.se</groupId>
+            <artifactId>weld-se-core</artifactId>
+            <version>2.4.1.Final</version>
+            <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.cdi.base</Bundle-SymbolicName>
+                        <Export-Package>org.apache.shiro.cdi*;version=${project.version}</Export-Package>
+                        <Import-Package>
+                            org.apache.shiro*;version="${shiro.osgi.importRange}",
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/CdiEnvironment.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/CdiEnvironment.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/CdiEnvironment.java
new file mode 100644
index 0000000..1177e2d
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/CdiEnvironment.java
@@ -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.cdi;
+
+import org.apache.shiro.env.Environment;
+import org.apache.shiro.mgt.SecurityManager;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+@ApplicationScoped
+public class CdiEnvironment implements Environment {
+
+    @Inject
+    private SecurityManager securityManager;
+
+    @Override
+    public SecurityManager getSecurityManager() {
+        return securityManager;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/EventListenerRegistrationInterceptor.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/EventListenerRegistrationInterceptor.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/EventListenerRegistrationInterceptor.java
new file mode 100644
index 0000000..ee31e5b
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/EventListenerRegistrationInterceptor.java
@@ -0,0 +1,74 @@
+/*
+ * 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.cdi;
+
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.event.EventBusAware;
+import org.apache.shiro.event.support.DefaultEventBus;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Priority;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.New;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InterceptorBinding;
+import javax.interceptor.InvocationContext;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@EventListenerRegistrationInterceptor.ProcessShiroEventBusConsumer
+@Interceptor
+@Priority(Interceptor.Priority.LIBRARY_BEFORE + 10)
+class EventListenerRegistrationInterceptor {
+
+    private final EventBus eventBus;
+
+    @Inject
+    public EventListenerRegistrationInterceptor(EventBus eventBus) {
+        this.eventBus = eventBus;
+    }
+
+    @PostConstruct
+    public Object invoke(final InvocationContext invocationContext) throws Throwable {
+
+        Object target = invocationContext.getTarget();
+
+        // If an object is EventBusAware, do NOT register events directly, just call setEventBus()
+        if(target instanceof EventBusAware) {
+            ((EventBusAware) target).setEventBus(eventBus);
+        }
+        else {
+            eventBus.register(target);
+        }
+
+        return invocationContext.proceed();
+    }
+
+    /**
+     * A marker annotation, used to assign Shiro annotations problematically.
+     */
+    @InterceptorBinding
+    @Target({ElementType.TYPE})
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface ProcessShiroEventBusConsumer {}
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/ShiroAnnotationInterceptor.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/ShiroAnnotationInterceptor.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/ShiroAnnotationInterceptor.java
new file mode 100644
index 0000000..e898be2
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/ShiroAnnotationInterceptor.java
@@ -0,0 +1,75 @@
+/*
+ * 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.cdi;
+
+import org.apache.shiro.aop.MethodInterceptor;
+import org.apache.shiro.aop.MethodInvocation;
+import org.apache.shiro.authz.aop.AnnotationsAuthorizingMethodInterceptor;
+
+import javax.annotation.Priority;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InterceptorBinding;
+import javax.interceptor.InvocationContext;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+
+@Interceptor
+@ShiroAnnotationInterceptor.ProcessShiroAnnotations
+@Priority(Interceptor.Priority.LIBRARY_BEFORE + 10)
+final class ShiroAnnotationInterceptor extends AnnotationsAuthorizingMethodInterceptor implements MethodInterceptor {
+
+    @AroundInvoke
+    public Object invoke(final InvocationContext invocationContext) throws Throwable {
+
+        return invoke(new MethodInvocation() {
+            @Override
+            public Object proceed() throws Throwable {
+                return invocationContext.proceed();
+            }
+
+            @Override
+            public Method getMethod() {
+                return invocationContext.getMethod();
+            }
+
+            @Override
+            public Object[] getArguments() {
+                return invocationContext.getParameters();
+            }
+
+            @Override
+            public Object getThis() {
+                return invocationContext.getTarget();
+            }
+        });
+    }
+
+    /**
+     * A marker annotation, used to assign Shiro annotations problematically.
+     */
+    @InterceptorBinding
+    @Target({ElementType.TYPE})
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface ProcessShiroAnnotations {}
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/ShiroCdiExtension.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/ShiroCdiExtension.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/ShiroCdiExtension.java
new file mode 100644
index 0000000..de6a7d9
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/ShiroCdiExtension.java
@@ -0,0 +1,191 @@
+/*
+ * 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.cdi;
+
+import org.apache.shiro.cdi.EventListenerRegistrationInterceptor.ProcessShiroEventBusConsumer;
+import org.apache.shiro.cdi.ShiroAnnotationInterceptor.ProcessShiroAnnotations;
+import org.apache.shiro.authz.annotation.RequiresAuthentication;
+import org.apache.shiro.authz.annotation.RequiresGuest;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.apache.shiro.authz.annotation.RequiresRoles;
+import org.apache.shiro.authz.annotation.RequiresUser;
+import org.apache.shiro.event.EventBusAware;
+import org.apache.shiro.event.Subscribe;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterDeploymentValidation;
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.ProcessBean;
+import javax.enterprise.inject.spi.WithAnnotations;
+import javax.enterprise.util.AnnotationLiteral;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ShiroCdiExtension implements Extension {
+
+    private List<Bean<?>> eagerBeansList = new ArrayList<Bean<?>>();
+
+    // Registering instances with Shiro's EventBus is a 4 part process:
+    // 1. registerEventListeners()/registerEventBusAware() detects any AnnotatedType with an 'Subscribe' annotation
+    //    and adds an additional annotation 'ProcessShiroEventBusConsumer' to mark the bean for interception
+    // 2. collectEventListeners() finds the Beans that were Annotated with 'ProcessShiroEventBusConsumer' and adds
+    //    them to the 'eagerBeansList'
+    // 3. eagerLoadBeans() initializes these beans
+    // 4. EventListenerRegistrationInterceptor adds a 'PostConstruct' interceptor that registers the instance with the
+    //    EventBus instance or calls setEventBus()
+
+    private <X> void registerEventBusAware(@Observes ProcessAnnotatedType<X> pat) {
+
+        if(EventBusAware.class.isAssignableFrom(pat.getAnnotatedType().getJavaClass())) {
+            addProcessShiroEventConsumerAnnotation(pat);
+        }
+    }
+
+    private <X> void registerEventListeners(@Observes @WithAnnotations({Subscribe.class}) ProcessAnnotatedType<X> pat) {
+        addProcessShiroEventConsumerAnnotation(pat);
+    }
+
+    private <X> void addProcessShiroEventConsumerAnnotation(ProcessAnnotatedType<X> pat) {
+
+        // wrap this to override the annotations of the class
+        final AnnotatedType<X> at = pat.getAnnotatedType();
+
+        pat.setAnnotatedType(new AdditionalAnntoationType<X, ProcessShiroEventBusConsumer>(at, ProcessShiroEventBusConsumer.class) {
+            @Override
+            public Set<Annotation> getAnnotations() {
+                Set<Annotation> original = at.getAnnotations();
+                Set<Annotation> annotations = new HashSet<>(original);
+                annotations.add(new AnnotationLiteral<ProcessShiroEventBusConsumer>() {});
+                return annotations;
+            }
+        });
+    }
+
+    private <T> void collectEventListeners(@Observes ProcessBean<T> event) {
+        if(event.getAnnotated().isAnnotationPresent(ApplicationScoped.class)) {
+            if(event.getAnnotated().isAnnotationPresent(ProcessShiroEventBusConsumer.class)
+                    || EventBusAware.class.isAssignableFrom(event.getBean().getBeanClass()) ) {
+                eagerBeansList.add(event.getBean());
+            }
+        }
+    }
+
+    private void eagerLoadBeans(@Observes AfterDeploymentValidation event, BeanManager beanManager) {
+        for (Bean<?> bean : eagerBeansList) {
+            // note: toString() is important to instantiate the bean
+            beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean)).toString();
+        }
+    }
+
+    /**
+     * Adds the {@link ProcessShiroAnnotations} annotation to any Bean containing one of the following annotations
+     * {@link RequiresAuthentication}, {@link RequiresGuest}, {@link RequiresUser}, {@link RequiresRoles},
+     * or {@link RequiresPermissions}.  This allows the {@link ShiroAnnotationInterceptor} to process the
+     * Shiro annotations.
+     */
+    private <X> void registerAuthAnnotations(@Observes @WithAnnotations({
+                                                    RequiresAuthentication.class,
+                                                    RequiresGuest.class,
+                                                    RequiresUser.class,
+                                                    RequiresRoles.class,
+                                                    RequiresPermissions.class})
+                                                ProcessAnnotatedType<X> pat) {
+
+        // wrap this to override the annotations of the class
+        final AnnotatedType<X> at = pat.getAnnotatedType();
+
+        pat.setAnnotatedType(new AdditionalAnntoationType<X, ProcessShiroAnnotations>(at, ProcessShiroAnnotations.class) {
+            @Override
+            public Set<Annotation> getAnnotations() {
+                Set<Annotation> original = at.getAnnotations();
+                Set<Annotation> annotations = new HashSet<>(original);
+
+                annotations.add(new AnnotationLiteral<ProcessShiroAnnotations>() {});
+
+                return annotations;
+            }
+        });
+    }
+
+    private abstract static class AdditionalAnntoationType<T, X extends Annotation> implements AnnotatedType<T> {
+
+        private final AnnotatedType<T> delegate;
+        private final Class<X> extraAnnotation;
+
+        private AdditionalAnntoationType(AnnotatedType<T> delegate, Class<X> extraAnnotation) {
+            this.delegate = delegate;
+            this.extraAnnotation = extraAnnotation;
+        }
+
+        @Override
+        public Set<AnnotatedConstructor<T>> getConstructors() {
+            return delegate.getConstructors();
+        }
+
+        @Override
+        public Set<AnnotatedField<? super T>> getFields() {
+            return delegate.getFields();
+        }
+
+        @Override
+        public Class<T> getJavaClass() {
+            return delegate.getJavaClass();
+        }
+
+        @Override
+        public Set<AnnotatedMethod<? super T>> getMethods() {
+            return delegate.getMethods();
+        }
+
+        @Override
+        public <T extends Annotation> T getAnnotation(final Class<T> annType) {
+            return delegate.getAnnotation(annType);
+        }
+
+        @Override
+        public Type getBaseType() {
+            return delegate.getBaseType();
+        }
+
+        @Override
+        public Set<Type> getTypeClosure() {
+            return delegate.getTypeClosure();
+        }
+
+        @Override
+        public boolean isAnnotationPresent(Class<? extends Annotation> annType) {
+            return extraAnnotation.equals(annType)
+                    || delegate.isAnnotationPresent(annType);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/Standard.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/Standard.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/Standard.java
new file mode 100644
index 0000000..6daff2e
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/Standard.java
@@ -0,0 +1,17 @@
+package org.apache.shiro.cdi;
+
+import javax.inject.Qualifier;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Qualifier
+@Retention(RUNTIME)
+@Target({TYPE, METHOD, FIELD, PARAMETER})
+public @interface Standard {
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/AbstractSecurityManagerProducer.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/AbstractSecurityManagerProducer.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/AbstractSecurityManagerProducer.java
new file mode 100644
index 0000000..80f1f10
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/AbstractSecurityManagerProducer.java
@@ -0,0 +1,134 @@
+/*
+ * 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.cdi.producers;
+
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
+import org.apache.shiro.authz.ModularRealmAuthorizer;
+import org.apache.shiro.authz.permission.PermissionResolver;
+import org.apache.shiro.authz.permission.RolePermissionResolver;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.event.EventBus;
+import org.apache.shiro.mgt.DefaultSecurityManager;
+import org.apache.shiro.mgt.RememberMeManager;
+import org.apache.shiro.mgt.SubjectDAO;
+import org.apache.shiro.mgt.SubjectFactory;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.util.Destroyable;
+import org.apache.shiro.util.Initializable;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AbstractSecurityManagerProducer {
+
+    @Inject
+    private Instance<Initializable> initializables;
+
+    @Inject
+    private Instance<Destroyable> destroyables;
+
+    @Inject
+    private Instance<Object> objectInstances;
+
+
+
+
+    protected abstract DefaultSecurityManager securityManager(DefaultSecurityManager securityManager,
+                                                              Instance<Realm> realms,
+                                                              EventBus eventBus,
+                                                              SessionManager sessionManager,
+                                                              Instance<CacheManager> cacheManager,
+                                                              SubjectDAO subjectDAO,
+                                                              SubjectFactory subjectFactory,
+                                                              Instance<RememberMeManager> rememberMeManager,
+                                                              AuthenticationStrategy authenticationStrategy,
+                                                              Instance<PermissionResolver> permissionResolver,
+                                                              Instance<RolePermissionResolver> rolePermissionResolver);
+
+
+    protected <T extends DefaultSecurityManager> T configureSecurityManager(T securityManager,
+                                                                            Instance<Realm> realms,
+                                                                            EventBus eventBus,
+                                                                            SessionManager sessionManager,
+                                                                            Instance<CacheManager> cacheManager,
+                                                                            SubjectDAO subjectDAO,
+                                                                            SubjectFactory subjectFactory,
+                                                                            Instance<RememberMeManager> rememberMeManager,
+                                                                            AuthenticationStrategy authenticationStrategy,
+                                                                            Instance<PermissionResolver> permissionResolver,
+                                                                            Instance<RolePermissionResolver> rolePermissionResolver) {
+        securityManager.setEventBus(eventBus);
+
+        // Set the cache manager if available
+        if(!cacheManager.isUnsatisfied()) {
+            securityManager.setCacheManager(cacheManager.get());
+        }
+
+        if(!rememberMeManager.isUnsatisfied()) {
+            securityManager.setRememberMeManager(rememberMeManager.get());
+        }
+
+        ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
+        authenticator.setAuthenticationStrategy(authenticationStrategy);
+        ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
+
+        if (permissionResolver != null && !permissionResolver.isUnsatisfied()) {
+            authorizer.setPermissionResolver(permissionResolver.get());
+        }
+
+        if (rolePermissionResolver != null && !rolePermissionResolver.isUnsatisfied()) {
+            authorizer.setRolePermissionResolver(rolePermissionResolver.get());
+        }
+
+        securityManager.setAuthenticator(authenticator);
+        securityManager.setAuthorizer(authorizer);
+        securityManager.setSessionManager(sessionManager);
+        securityManager.setSubjectDAO(subjectDAO);
+        securityManager.setSubjectFactory(subjectFactory);
+
+        List<Realm> realmList = new ArrayList<>();
+        for (Realm realm : realms) {
+            realmList.add(realm);
+        }
+        securityManager.setRealms(realmList);
+
+        return securityManager;
+    }
+
+
+//    @PostConstruct
+//    void init() {
+//        for(Initializable initializable : initializables) {
+//            initializable.init();
+//        }
+//    }
+
+//    @PreDestroy
+//    void destroy() throws Exception {
+//        for(Destroyable destroyable : destroyables) {
+//            destroyable.destroy();
+//        }
+//    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/AuthenticationStrategyProducer.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/AuthenticationStrategyProducer.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/AuthenticationStrategyProducer.java
new file mode 100644
index 0000000..ef1c976
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/AuthenticationStrategyProducer.java
@@ -0,0 +1,15 @@
+package org.apache.shiro.cdi.producers;
+
+import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
+
+import javax.enterprise.inject.New;
+import javax.enterprise.inject.Produces;
+
+public class AuthenticationStrategyProducer {
+
+    @Produces
+    protected AtLeastOneSuccessfulStrategy authenticationStrategy(@New AtLeastOneSuccessfulStrategy authenticationStrategy) {
+        return authenticationStrategy;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/EventBusProducer.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/EventBusProducer.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/EventBusProducer.java
new file mode 100644
index 0000000..4c56d89
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/EventBusProducer.java
@@ -0,0 +1,16 @@
+package org.apache.shiro.cdi.producers;
+
+import org.apache.shiro.event.support.DefaultEventBus;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.New;
+import javax.enterprise.inject.Produces;
+
+public class EventBusProducer {
+
+    @Produces
+    @ApplicationScoped
+    DefaultEventBus eventBusWTF(@New DefaultEventBus eventBus) {
+        return eventBus;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SessionFactoryProducer.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SessionFactoryProducer.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SessionFactoryProducer.java
new file mode 100644
index 0000000..f0984c3
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SessionFactoryProducer.java
@@ -0,0 +1,15 @@
+package org.apache.shiro.cdi.producers;
+
+import org.apache.shiro.session.mgt.SessionFactory;
+import org.apache.shiro.session.mgt.SimpleSessionFactory;
+
+import javax.enterprise.inject.New;
+import javax.enterprise.inject.Produces;
+
+public class SessionFactoryProducer {
+
+    @Produces
+    protected SessionFactory sessionFactory(@New SimpleSessionFactory sessionFactory) {
+        return sessionFactory;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SessionStorageEvaluatorProducer.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SessionStorageEvaluatorProducer.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SessionStorageEvaluatorProducer.java
new file mode 100644
index 0000000..473a11e
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SessionStorageEvaluatorProducer.java
@@ -0,0 +1,14 @@
+package org.apache.shiro.cdi.producers;
+
+import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
+
+import javax.enterprise.inject.New;
+import javax.enterprise.inject.Produces;
+
+public class SessionStorageEvaluatorProducer {
+
+    @Produces
+    DefaultSessionStorageEvaluator sessionStorageEvaluator(@New DefaultSessionStorageEvaluator sessionStorageEvaluator) {
+        return sessionStorageEvaluator;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SubjectDaoProducer.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SubjectDaoProducer.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SubjectDaoProducer.java
new file mode 100644
index 0000000..aa3a6d5
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SubjectDaoProducer.java
@@ -0,0 +1,16 @@
+package org.apache.shiro.cdi.producers;
+
+import org.apache.shiro.mgt.DefaultSubjectDAO;
+import org.apache.shiro.mgt.SessionStorageEvaluator;
+
+import javax.enterprise.inject.New;
+import javax.enterprise.inject.Produces;
+
+public class SubjectDaoProducer {
+
+    @Produces
+    DefaultSubjectDAO subjectDAO(@New DefaultSubjectDAO subjectDAO, SessionStorageEvaluator sessionStorageEvaluator) {
+        subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator);
+        return subjectDAO;
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SubjectProducer.java
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SubjectProducer.java b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SubjectProducer.java
new file mode 100644
index 0000000..cd28db6
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/java/org/apache/shiro/cdi/producers/SubjectProducer.java
@@ -0,0 +1,21 @@
+package org.apache.shiro.cdi.producers;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.ThreadContext;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Produces;
+
+public class SubjectProducer {
+
+    @Produces
+    @RequestScoped
+    protected Subject subject(SecurityManager securityManager) {
+        if (ThreadContext.getSecurityManager() == null) {
+            ThreadContext.bind(securityManager);
+        }
+        return SecurityUtils.getSubject();
+    }
+}

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/resources/META-INF/beans.xml
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/resources/META-INF/beans.xml b/support/cdi/cdi-base/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..632b301
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,7 @@
+<beans>
+    <!--xmlns="http://xmlns.jcp.org/xml/ns/javaee"-->
+       <!--xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"-->
+       <!--xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee-->
+                           <!--http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"-->
+       <!--bean-discovery-mode="all">-->
+</beans>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/support/cdi/cdi-base/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..1e6701c
--- /dev/null
+++ b/support/cdi/cdi-base/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.apache.shiro.cdi.ShiroCdiExtension

http://git-wip-us.apache.org/repos/asf/shiro/blob/59b944c0/support/cdi/cdi-base/src/test/groovy/org/apache/shiro/cdi/CdiHackingTest.groovy
----------------------------------------------------------------------
diff --git a/support/cdi/cdi-base/src/test/groovy/org/apache/shiro/cdi/CdiHackingTest.groovy b/support/cdi/cdi-base/src/test/groovy/org/apache/shiro/cdi/CdiHackingTest.groovy
new file mode 100644
index 0000000..4d687cc
--- /dev/null
+++ b/support/cdi/cdi-base/src/test/groovy/org/apache/shiro/cdi/CdiHackingTest.groovy
@@ -0,0 +1,112 @@
+/*
+ * 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.cdi
+
+import org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner
+import org.apache.shiro.authc.Authenticator
+import org.apache.shiro.authz.Authorizer
+import org.apache.shiro.authz.permission.PermissionResolver
+import org.apache.shiro.cache.CacheManager
+import org.apache.shiro.event.EventBus
+import org.apache.shiro.mgt.DefaultSecurityManager
+import org.apache.shiro.mgt.RememberMeManager
+import org.apache.shiro.mgt.SecurityManager
+import org.apache.shiro.mgt.SubjectDAO
+import org.apache.shiro.mgt.SubjectFactory
+import org.apache.shiro.realm.Realm
+import org.apache.shiro.session.mgt.DefaultSessionKey
+import org.apache.shiro.session.mgt.SessionManager
+import org.apache.shiro.subject.Subject
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import javax.enterprise.context.ApplicationScoped
+import javax.enterprise.inject.Default
+import javax.enterprise.inject.Instance
+import javax.inject.Inject
+
+import static org.hamcrest.Matchers.*
+
+import static org.junit.Assert.*
+
+/**
+ * Hacking around with CDI and Shiro.
+ */
+@RunWith(CdiTestRunner.class)
+@Default
+@ApplicationScoped
+public class CdiHackingTest {
+
+//    @Inject
+//    private SecurityManager securityManager;
+//
+//    @Inject
+//    private CdiEnvironment cdiEnvironment;
+//
+//    @Inject
+//    private EventBus eventBus;
+//
+//    @Inject
+//    private Instance<Realm> realms;
+//
+//    @Inject
+//    private SessionManager sessionManager
+//
+//    @Inject
+//    private Instance<CacheManager> cacheManager;
+//
+//    @Inject
+//    private SubjectDAO subjectDAO;
+//
+//    @Inject
+//    private SubjectFactory subjectFactory;
+//
+//    @Inject
+//    private Instance<RememberMeManager> rememberMeManager;
+//
+//    @Inject
+//    private Instance<PermissionResolver> permissionResolver;
+//
+//    @Inject
+//    private Subject subject;
+
+    @Test
+    public void doSomeStuff() {
+
+//        assertNotNull(eventBus)
+//        assertNotNull(subjectFactory)
+//        assertNotNull(subjectDAO)
+//        assertNotNull(sessionManager)
+//
+//        assertTrue(rememberMeManager.isUnsatisfied())
+//        assertTrue(cacheManager.isUnsatisfied())
+//
+//        assertNotNull(permissionResolver.get())
+//
+//        assertSame cdiEnvironment.securityManager, securityManager
+//        assertThat securityManager, instanceOf(DefaultSecurityManager)
+//
+//        assertEquals sessionManager, securityManager.getSessionManager()
+////        sessionManager.getSession(new DefaultSessionKey("foo"))
+//
+//        assertFalse subject.isAuthenticated()
+
+
+    }
+}