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