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 */ 019package org.apache.shiro.mgt; 020 021import org.apache.shiro.cache.CacheManager; 022import org.apache.shiro.cache.CacheManagerAware; 023import org.apache.shiro.event.EventBus; 024import org.apache.shiro.event.EventBusAware; 025import org.apache.shiro.realm.Realm; 026import org.apache.shiro.util.LifecycleUtils; 027 028import java.util.ArrayList; 029import java.util.Collection; 030 031 032/** 033 * Shiro support of a {@link SecurityManager} class hierarchy based around a collection of 034 * {@link org.apache.shiro.realm.Realm}s. All actual {@code SecurityManager} method implementations are left to 035 * subclasses. 036 * 037 * @since 0.9 038 */ 039public abstract class RealmSecurityManager extends CachingSecurityManager { 040 041 /** 042 * Internal collection of <code>Realm</code>s used for all authentication and authorization operations. 043 */ 044 private Collection<Realm> realms; 045 046 /** 047 * Default no-arg constructor. 048 */ 049 public RealmSecurityManager() { 050 super(); 051 } 052 053 /** 054 * Convenience method for applications using a single realm that merely wraps the realm in a list and then invokes 055 * the {@link #setRealms} method. 056 * 057 * @param realm the realm to set for a single-realm application. 058 * @since 0.2 059 */ 060 public void setRealm(Realm realm) { 061 if (realm == null) { 062 throw new IllegalArgumentException("Realm argument cannot be null"); 063 } 064 Collection<Realm> realms = new ArrayList<Realm>(1); 065 realms.add(realm); 066 setRealms(realms); 067 } 068 069 /** 070 * Sets the realms managed by this <tt>SecurityManager</tt> instance. 071 * 072 * @param realms the realms managed by this <tt>SecurityManager</tt> instance. 073 * @throws IllegalArgumentException if the realms collection is null or empty. 074 */ 075 public void setRealms(Collection<Realm> realms) { 076 if (realms == null) { 077 throw new IllegalArgumentException("Realms collection argument cannot be null."); 078 } 079 if (realms.isEmpty()) { 080 throw new IllegalArgumentException("Realms collection argument cannot be empty."); 081 } 082 this.realms = realms; 083 afterRealmsSet(); 084 } 085 086 protected void afterRealmsSet() { 087 applyCacheManagerToRealms(); 088 applyEventBusToRealms(); 089 } 090 091 /** 092 * Returns the {@link Realm Realm}s managed by this SecurityManager instance. 093 * 094 * @return the {@link Realm Realm}s managed by this SecurityManager instance. 095 */ 096 public Collection<Realm> getRealms() { 097 return realms; 098 } 099 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}