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.env.DefaultEnvironment; 20 21 import hunt.shiro.env.NamedObjectEnvironment; 22 23 import hunt.shiro.Exceptions; 24 import hunt.shiro.mgt.SecurityManager; 25 import hunt.shiro.util.Common; 26 import hunt.shiro.util.LifecycleUtils; 27 28 import hunt.collection; 29 import hunt.Exceptions; 30 31 import std.array; 32 33 /** 34 * Simple/default {@code Environment} implementation that stores Shiro objects as key-value pairs in a 35 * {@link java.util.Map Map} instance. The key is the object name, the value is the object itself. 36 * 37 */ 38 class DefaultEnvironment : NamedObjectEnvironment, Destroyable { 39 40 /** 41 * The default name under which the application's {@code SecurityManager} instance may be acquired, equal to 42 * {@code securityManager}. 43 */ 44 enum string DEFAULT_SECURITY_MANAGER_KEY = "securityManager"; 45 46 protected Map!(string, Object) objects; 47 private string securityManagerName; 48 49 /** 50 * Creates a new instance with a thread-safe {@link ConcurrentHashMap} backing map. 51 */ 52 this() { 53 this(new HashMap!(string, Object)()); 54 } 55 56 /** 57 * Creates a new instance with the specified backing map. 58 * 59 * @param seed backing map to use to maintain Shiro objects. 60 */ 61 this(Map!(string, Object) seed) { 62 this.securityManagerName = DEFAULT_SECURITY_MANAGER_KEY; 63 if (seed is null) { 64 throw new IllegalArgumentException("Backing map cannot be null."); 65 } 66 this.objects = seed; 67 } 68 69 /** 70 * Returns the application's {@code SecurityManager} instance accessible in the backing map using the 71 * {@link #getSecurityManagerName() securityManagerName} property as the lookup key. 72 * <p/> 73 * This implementation guarantees that a non-null instance is always returned, as this is expected for 74 * Environment API end-users. If subclasses have the need to perform the map lookup without this guarantee 75 * (for example, during initialization when the instance may not have been added to the map yet), the 76 * {@link #lookupSecurityManager()} method is provided as an alternative. 77 * 78 * @return the application's {@code SecurityManager} instance accessible in the backing map using the 79 * {@link #getSecurityManagerName() securityManagerName} property as the lookup key. 80 */ 81 SecurityManager getSecurityManager(){ 82 SecurityManager securityManager = lookupSecurityManager(); 83 if (securityManager is null) { 84 throw new IllegalStateException("No SecurityManager found in Environment. This is an invalid " ~ 85 "environment state."); 86 } 87 return securityManager; 88 } 89 90 void setSecurityManager(SecurityManager securityManager) { 91 if (securityManager is null) { 92 throw new IllegalArgumentException("Null SecurityManager instances are not allowed."); 93 } 94 string name = getSecurityManagerName(); 95 setObject(name, cast(Object)securityManager); 96 } 97 98 /** 99 * Looks up the {@code SecurityManager} instance in the backing map without performing any non-null guarantees. 100 * 101 * @return the {@code SecurityManager} in the backing map, or {@code null} if it has not yet been populated. 102 */ 103 protected SecurityManager lookupSecurityManager() { 104 string name = getSecurityManagerName(); 105 return cast(SecurityManager)getObject(name); 106 } 107 108 /** 109 * Returns the name of the {@link SecurityManager} instance in the backing map. Used as a key to lookup the 110 * instance. Unless set otherwise, the default is {@code securityManager}. 111 * 112 * @return the name of the {@link SecurityManager} instance in the backing map. Used as a key to lookup the 113 * instance. 114 */ 115 string getSecurityManagerName() { 116 return securityManagerName; 117 } 118 119 /** 120 * Sets the name of the {@link SecurityManager} instance in the backing map. Used as a key to lookup the 121 * instance. Unless set otherwise, the default is {@code securityManager}. 122 * 123 * @param securityManagerName the name of the {@link SecurityManager} instance in the backing map. Used as a key 124 * to lookup the instance. 125 */ 126 void setSecurityManagerName(string securityManagerName) { 127 this.securityManagerName = securityManagerName; 128 } 129 130 /** 131 * Returns the live (modifiable) internal objects collection. 132 * 133 * @return the live (modifiable) internal objects collection. 134 */ 135 Map!(string,Object) getObjects() { 136 return this.objects; 137 } 138 139 //@SuppressWarnings({"unchecked"}) 140 Object getObject(string name) { // , TypeInfo requiredType 141 if (name.empty()) { 142 throw new NullPointerException("name parameter cannot be null."); 143 } 144 // if (requiredType is null) { 145 // throw new NullPointerException("requiredType parameter cannot be null."); 146 // } 147 Object o = this.objects.get(name); 148 if (o is null) { 149 return null; 150 } 151 152 // if (requiredType != typeid(o)) { 153 // string msg = "Object named '" ~ name ~ "' is not of required type [" ~ requiredType.toString() ~ "]."; 154 // throw new RequiredTypeException(msg); 155 // } 156 return o; 157 } 158 159 void setObject(string name, Object instance) { 160 if (name is null) { 161 throw new NullPointerException("name parameter cannot be null."); 162 } 163 if (instance is null) { 164 this.objects.remove(name); 165 } else { 166 this.objects.put(name, instance); 167 } 168 } 169 170 void destroy(){ 171 LifecycleUtils.destroy(this.objects.values()); 172 } 173 }