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.event.EventBus;
24  import org.apache.shiro.event.EventBusAware;
25  import org.apache.shiro.realm.Realm;
26  import org.apache.shiro.util.LifecycleUtils;
27  
28  import java.util.ArrayList;
29  import java.util.Collection;
30  
31  
32  /**
33   * Shiro support of a {@link SecurityManager} class hierarchy based around a collection of
34   * {@link org.apache.shiro.realm.Realm}s.  All actual {@code SecurityManager} method implementations are left to
35   * subclasses.
36   *
37   * @since 0.9
38   */
39  public abstract class RealmSecurityManager extends CachingSecurityManager {
40  
41      /**
42       * Internal collection of <code>Realm</code>s used for all authentication and authorization operations.
43       */
44      private Collection<Realm> realms;
45  
46      /**
47       * Default no-arg constructor.
48       */
49      public RealmSecurityManager() {
50          super();
51      }
52  
53      /**
54       * Convenience method for applications using a single realm that merely wraps the realm in a list and then invokes
55       * the {@link #setRealms} method.
56       *
57       * @param realm the realm to set for a single-realm application.
58       * @since 0.2
59       */
60      public void setRealm(Realm realm) {
61          if (realm == null) {
62              throw new IllegalArgumentException("Realm argument cannot be null");
63          }
64          Collection<Realm> realms = new ArrayList<Realm>(1);
65          realms.add(realm);
66          setRealms(realms);
67      }
68  
69      /**
70       * Sets the realms managed by this <tt>SecurityManager</tt> instance.
71       *
72       * @param realms the realms managed by this <tt>SecurityManager</tt> instance.
73       * @throws IllegalArgumentException if the realms collection is null or empty.
74       */
75      public void setRealms(Collection<Realm> realms) {
76          if (realms == null) {
77              throw new IllegalArgumentException("Realms collection argument cannot be null.");
78          }
79          if (realms.isEmpty()) {
80              throw new IllegalArgumentException("Realms collection argument cannot be empty.");
81          }
82          this.realms = realms;
83          afterRealmsSet();
84      }
85  
86      protected void afterRealmsSet() {
87          applyCacheManagerToRealms();
88          applyEventBusToRealms();
89      }
90  
91      /**
92       * Returns the {@link Realm Realm}s managed by this SecurityManager instance.
93       *
94       * @return the {@link Realm Realm}s managed by this SecurityManager instance.
95       */
96      public Collection<Realm> getRealms() {
97          return realms;
98      }
99  
100     /**
101      * Sets the internal {@link #getCacheManager CacheManager} on any internal configured
102      * {@link #getRealms Realms} that implement the {@link org.apache.shiro.cache.CacheManagerAware CacheManagerAware} interface.
103      * <p/>
104      * This method is called after setting a cacheManager on this securityManager via the
105      * {@link #setCacheManager(org.apache.shiro.cache.CacheManager) setCacheManager} method to allow it to be propagated
106      * down to all the internal Realms that would need to use it.
107      * <p/>
108      * It is also called after setting one or more realms via the {@link #setRealm setRealm} or
109      * {@link #setRealms setRealms} methods to allow these newly available realms to be given the cache manager
110      * already in use.
111      */
112     protected void applyCacheManagerToRealms() {
113         CacheManager cacheManager = getCacheManager();
114         Collection<Realm> realms = getRealms();
115         if (cacheManager != null && realms != null && !realms.isEmpty()) {
116             for (Realm realm : realms) {
117                 if (realm instanceof CacheManagerAware) {
118                     ((CacheManagerAware) realm).setCacheManager(cacheManager);
119                 }
120             }
121         }
122     }
123 
124     /**
125      * Sets the internal {@link #getEventBus  EventBus} on any internal configured
126      * {@link #getRealms Realms} that implement the {@link EventBusAware} interface.
127      * <p/>
128      * This method is called after setting an eventBus on this securityManager via the
129      * {@link #setEventBus(org.apache.shiro.event.EventBus) setEventBus} method to allow it to be propagated
130      * down to all the internal Realms that would need to use it.
131      * <p/>
132      * It is also called after setting one or more realms via the {@link #setRealm setRealm} or
133      * {@link #setRealms setRealms} methods to allow these newly available realms to be given the EventBus
134      * already in use.
135      *
136      * @since 1.3
137      */
138     protected void applyEventBusToRealms() {
139         EventBus eventBus = getEventBus();
140         Collection<Realm> realms = getRealms();
141         if (eventBus != null && realms != null && !realms.isEmpty()) {
142             for(Realm realm : realms) {
143                 if (realm instanceof EventBusAware) {
144                     ((EventBusAware)realm).setEventBus(eventBus);
145                 }
146             }
147         }
148     }
149 
150     /**
151      * Simply calls {@link #applyCacheManagerToRealms() applyCacheManagerToRealms()} to allow the
152      * newly set {@link org.apache.shiro.cache.CacheManager CacheManager} to be propagated to the internal collection of <code>Realm</code>
153      * that would need to use it.
154      */
155     protected void afterCacheManagerSet() {
156         super.afterCacheManagerSet();
157         applyCacheManagerToRealms();
158     }
159 
160     @Override
161     protected void afterEventBusSet() {
162         super.afterEventBusSet();
163         applyEventBusToRealms();
164     }
165 
166     public void destroy() {
167         LifecycleUtils.destroy(getRealms());
168         this.realms = null;
169         super.destroy();
170     }
171 
172 }