View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.mgt;
20  
21  import org.apache.shiro.cache.CacheManager;
22  import org.apache.shiro.cache.CacheManagerAware;
23  import org.apache.shiro.realm.Realm;
24  import org.apache.shiro.util.LifecycleUtils;
25  
26  import java.util.ArrayList;
27  import java.util.Collection;
28  
29  
30  /**
31   * Shiro support of a {@link SecurityManager} class hierarchy based around a collection of
32   * {@link org.apache.shiro.realm.Realm}s.  All actual {@code SecurityManager} method implementations are left to
33   * subclasses.
34   *
35   * @since 0.9
36   */
37  public abstract class RealmSecurityManager extends CachingSecurityManager {
38  
39      /**
40       * Internal collection of <code>Realm</code>s used for all authentication and authorization operations.
41       */
42      private Collection<Realm> realms;
43  
44      /**
45       * Default no-arg constructor.
46       */
47      public RealmSecurityManager() {
48          super();
49      }
50  
51      /**
52       * Convenience method for applications using a single realm that merely wraps the realm in a list and then invokes
53       * the {@link #setRealms} method.
54       *
55       * @param realm the realm to set for a single-realm application.
56       * @since 0.2
57       */
58      public void setRealm(Realm realm) {
59          if (realm == null) {
60              throw new IllegalArgumentException("Realm argument cannot be null");
61          }
62          Collection<Realm> realms = new ArrayList<Realm>(1);
63          realms.add(realm);
64          setRealms(realms);
65      }
66  
67      /**
68       * Sets the realms managed by this <tt>SecurityManager</tt> instance.
69       *
70       * @param realms the realms managed by this <tt>SecurityManager</tt> instance.
71       * @throws IllegalArgumentException if the realms collection is null or empty.
72       */
73      public void setRealms(Collection<Realm> realms) {
74          if (realms == null) {
75              throw new IllegalArgumentException("Realms collection argument cannot be null.");
76          }
77          if (realms.isEmpty()) {
78              throw new IllegalArgumentException("Realms collection argument cannot be empty.");
79          }
80          this.realms = realms;
81          afterRealmsSet();
82      }
83  
84      protected void afterRealmsSet() {
85          applyCacheManagerToRealms();
86      }
87  
88      /**
89       * Returns the {@link Realm Realm}s managed by this SecurityManager instance.
90       *
91       * @return the {@link Realm Realm}s managed by this SecurityManager instance.
92       */
93      public Collection<Realm> getRealms() {
94          return realms;
95      }
96  
97      /**
98       * Sets the internal {@link #getCacheManager CacheManager} on any internal configured
99       * {@link #getRealms Realms} that implement the {@link org.apache.shiro.cache.CacheManagerAware CacheManagerAware} interface.
100      * <p/>
101      * This method is called after setting a cacheManager on this securityManager via the
102      * {@link #setCacheManager(org.apache.shiro.cache.CacheManager) setCacheManager} method to allow it to be propagated
103      * down to all the internal Realms that would need to use it.
104      * <p/>
105      * It is also called after setting one or more realms via the {@link #setRealm setRealm} or
106      * {@link #setRealms setRealms} methods to allow these newly available realms to be given the cache manager
107      * already in use.
108      */
109     protected void applyCacheManagerToRealms() {
110         CacheManager cacheManager = getCacheManager();
111         Collection<Realm> realms = getRealms();
112         if (cacheManager != null && realms != null && !realms.isEmpty()) {
113             for (Realm realm : realms) {
114                 if (realm instanceof CacheManagerAware) {
115                     ((CacheManagerAware) realm).setCacheManager(cacheManager);
116                 }
117             }
118         }
119     }
120 
121     /**
122      * Simply calls {@link #applyCacheManagerToRealms() applyCacheManagerToRealms()} to allow the
123      * newly set {@link org.apache.shiro.cache.CacheManager CacheManager} to be propagated to the internal collection of <code>Realm</code>
124      * that would need to use it.
125      */
126     protected void afterCacheManagerSet() {
127         applyCacheManagerToRealms();
128     }
129 
130     public void destroy() {
131         LifecycleUtils.destroy(getRealms());
132         this.realms = null;
133         super.destroy();
134     }
135 
136 }