/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.shiro.env; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.util.Destroyable; import org.apache.shiro.util.LifecycleUtils; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Simple/default {@code Environment} implementation that stores Shiro objects as key-value pairs in a * {@link java.util.Map Map} instance. The key is the object name, the value is the object itself. * * @since 1.2 */ public class DefaultEnvironment implements NamedObjectEnvironment, Destroyable { /** * The default name under which the application's {@code SecurityManager} instance may be acquired, equal to * {@code securityManager}. */ public static final String DEFAULT_SECURITY_MANAGER_KEY = "securityManager"; protected final Map<String, Object> objects; private String securityManagerName; /** * Creates a new instance with a thread-safe {@link ConcurrentHashMap} backing map. */ public DefaultEnvironment() { this(new ConcurrentHashMap<String, Object>()); } /** * Creates a new instance with the specified backing map. * * @param seed backing map to use to maintain Shiro objects. */ @SuppressWarnings({"unchecked"}) public DefaultEnvironment(Map<String, ?> seed) { this.securityManagerName = DEFAULT_SECURITY_MANAGER_KEY; if (seed == null) { throw new IllegalArgumentException("Backing map cannot be null."); } this.objects = (Map<String, Object>) seed; } /** * Returns the application's {@code SecurityManager} instance accessible in the backing map using the * {@link #getSecurityManagerName() securityManagerName} property as the lookup key. * <p/> * This implementation guarantees that a non-null instance is always returned, as this is expected for * Environment API end-users. If subclasses have the need to perform the map lookup without this guarantee * (for example, during initialization when the instance may not have been added to the map yet), the * {@link #lookupSecurityManager()} method is provided as an alternative. * * @return the application's {@code SecurityManager} instance accessible in the backing map using the * {@link #getSecurityManagerName() securityManagerName} property as the lookup key. */ public SecurityManager getSecurityManager() throws IllegalStateException { SecurityManager securityManager = lookupSecurityManager(); if (securityManager == null) { throw new IllegalStateException("No SecurityManager found in Environment. This is an invalid " + "environment state."); } return securityManager; } public void setSecurityManager(SecurityManager securityManager) { if (securityManager == null) { throw new IllegalArgumentException("Null SecurityManager instances are not allowed."); } String name = getSecurityManagerName(); setObject(name, securityManager); } /** * Looks up the {@code SecurityManager} instance in the backing map without performing any non-null guarantees. * * @return the {@code SecurityManager} in the backing map, or {@code null} if it has not yet been populated. */ protected SecurityManager lookupSecurityManager() { String name = getSecurityManagerName(); return getObject(name, SecurityManager.class); } /** * Returns the name of the {@link SecurityManager} instance in the backing map. Used as a key to lookup the * instance. Unless set otherwise, the default is {@code securityManager}. * * @return the name of the {@link SecurityManager} instance in the backing map. Used as a key to lookup the * instance. */ public String getSecurityManagerName() { return securityManagerName; } /** * Sets the name of the {@link SecurityManager} instance in the backing map. Used as a key to lookup the * instance. Unless set otherwise, the default is {@code securityManager}. * * @param securityManagerName the name of the {@link SecurityManager} instance in the backing map. Used as a key * to lookup the instance.  */ public void setSecurityManagerName(String securityManagerName) { this.securityManagerName = securityManagerName; } /** * Returns the live (modifiable) internal objects collection. * * @return the live (modifiable) internal objects collection. */ public Map<String,Object> getObjects() { return this.objects; } @SuppressWarnings({"unchecked"}) public <T> T getObject(String name, Class<T> requiredType) throws RequiredTypeException { if (name == null) { throw new NullPointerException("name parameter cannot be null."); } if (requiredType == null) { throw new NullPointerException("requiredType parameter cannot be null."); } Object o = this.objects.get(name); if (o == null) { return null; } if (!requiredType.isInstance(o)) { String msg = "Object named '" + name + "' is not of required type [" + requiredType.getName() + "]."; throw new RequiredTypeException(msg); } return (T)o; } public void setObject(String name, Object instance) { if (name == null) { throw new NullPointerException("name parameter cannot be null."); } if (instance == null) { this.objects.remove(name); } else { this.objects.put(name, instance); } } public void destroy() throws Exception { LifecycleUtils.destroy(this.objects.values()); } }