001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.mgt;
020
021 import org.apache.shiro.cache.CacheManager;
022 import org.apache.shiro.cache.CacheManagerAware;
023 import org.apache.shiro.realm.Realm;
024 import org.apache.shiro.util.LifecycleUtils;
025
026 import java.util.ArrayList;
027 import java.util.Collection;
028
029
030 /**
031 * Shiro support of a {@link SecurityManager} class hierarchy based around a collection of
032 * {@link org.apache.shiro.realm.Realm}s. All actual {@code SecurityManager} method implementations are left to
033 * subclasses.
034 *
035 * @author Les Hazlewood
036 * @since 0.9
037 */
038 public abstract class RealmSecurityManager extends CachingSecurityManager {
039
040 /**
041 * Internal collection of <code>Realm</code>s used for all authentication and authorization operations.
042 */
043 private Collection<Realm> realms;
044
045 /**
046 * Default no-arg constructor.
047 */
048 public RealmSecurityManager() {
049 super();
050 }
051
052 /**
053 * Convenience method for applications using a single realm that merely wraps the realm in a list and then invokes
054 * the {@link #setRealms} method.
055 *
056 * @param realm the realm to set for a single-realm application.
057 * @since 0.2
058 */
059 public void setRealm(Realm realm) {
060 if (realm == null) {
061 throw new IllegalArgumentException("Realm argument cannot be null");
062 }
063 Collection<Realm> realms = new ArrayList<Realm>(1);
064 realms.add(realm);
065 setRealms(realms);
066 }
067
068 /**
069 * Sets the realms managed by this <tt>SecurityManager</tt> instance.
070 *
071 * @param realms the realms managed by this <tt>SecurityManager</tt> instance.
072 * @throws IllegalArgumentException if the realms collection is null or empty.
073 */
074 public void setRealms(Collection<Realm> realms) {
075 if (realms == null) {
076 throw new IllegalArgumentException("Realms collection argument cannot be null.");
077 }
078 if (realms.isEmpty()) {
079 throw new IllegalArgumentException("Realms collection argument cannot be empty.");
080 }
081 this.realms = realms;
082 afterRealmsSet();
083 }
084
085 protected void afterRealmsSet() {
086 applyCacheManagerToRealms();
087 }
088
089 /**
090 * Returns the {@link Realm Realm}s managed by this SecurityManager instance.
091 *
092 * @return the {@link Realm Realm}s managed by this SecurityManager instance.
093 */
094 public Collection<Realm> getRealms() {
095 return realms;
096 }
097
098 /**
099 * Sets the internal {@link #getCacheManager CacheManager} on any internal configured
100 * {@link #getRealms Realms} that implement the {@link org.apache.shiro.cache.CacheManagerAware CacheManagerAware} interface.
101 * <p/>
102 * This method is called after setting a cacheManager on this securityManager via the
103 * {@link #setCacheManager(org.apache.shiro.cache.CacheManager) setCacheManager} method to allow it to be propagated
104 * down to all the internal Realms that would need to use it.
105 * <p/>
106 * It is also called after setting one or more realms via the {@link #setRealm setRealm} or
107 * {@link #setRealms setRealms} methods to allow these newly available realms to be given the cache manager
108 * already in use.
109 */
110 protected void applyCacheManagerToRealms() {
111 CacheManager cacheManager = getCacheManager();
112 Collection<Realm> realms = getRealms();
113 if (cacheManager != null && realms != null && !realms.isEmpty()) {
114 for (Realm realm : realms) {
115 if (realm instanceof CacheManagerAware) {
116 ((CacheManagerAware) realm).setCacheManager(cacheManager);
117 }
118 }
119 }
120 }
121
122 /**
123 * Simply calls {@link #applyCacheManagerToRealms() applyCacheManagerToRealms()} to allow the
124 * newly set {@link org.apache.shiro.cache.CacheManager CacheManager} to be propagated to the internal collection of <code>Realm</code>
125 * that would need to use it.
126 */
127 protected void afterCacheManagerSet() {
128 applyCacheManagerToRealms();
129 }
130
131 public void destroy() {
132 LifecycleUtils.destroy(getRealms());
133 this.realms = null;
134 super.destroy();
135 }
136
137 }