killbill-aplcache

Details

diff --git a/profiles/killbill/src/main/java/org/apache/shiro/guice/web/ShiroWebModuleWith435.java b/profiles/killbill/src/main/java/org/apache/shiro/guice/web/ShiroWebModuleWith435.java
new file mode 100644
index 0000000..f877740
--- /dev/null
+++ b/profiles/killbill/src/main/java/org/apache/shiro/guice/web/ShiroWebModuleWith435.java
@@ -0,0 +1,257 @@
+/*
+ * 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.ServletContainerSessionManager;
+
+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.
+ * @see <a href="https://issues.apache.org/jira/browse/SHIRO-435">https://issues.apache.org/jira/browse/SHIRO-435</a>
+ */
+public abstract class ShiroWebModuleWith435 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 ShiroWebModuleWith435(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() {
+        bindBeanType(TypeLiteral.get(ServletContext.class), Key.get(ServletContext.class, Names.named(NAME)));
+        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) {
+        bind.to(WebSecurityManager.class); // SHIRO-435
+    }
+
+    /**
+     * 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(ServletContainerSessionManager.class).asEagerSingleton();
+    }
+
+    @Override
+    protected final void bindEnvironment(AnnotatedBindingBuilder<Environment> bind) {
+        bind.to(WebEnvironment.class); // SHIRO-435
+    }
+
+    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;
+        }
+    }
+}
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
index 0617b12..96cd7ef 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
@@ -24,7 +24,7 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.shiro.cache.CacheManager;
-import org.apache.shiro.guice.web.ShiroWebModule;
+import org.apache.shiro.guice.web.ShiroWebModuleWith435;
 import org.apache.shiro.session.mgt.SessionManager;
 import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
 import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
@@ -46,7 +46,7 @@ import com.google.inject.binder.AnnotatedBindingBuilder;
 
 // For Kill Bill server only.
 // See org.killbill.billing.util.glue.KillBillShiroModule for Kill Bill library.
-public class KillBillShiroWebModule extends ShiroWebModule {
+public class KillBillShiroWebModule extends ShiroWebModuleWith435 {
 
     private final ConfigSource configSource;