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