/* * 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.realm.jndi; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.apache.shiro.jndi.JndiLocator; import org.apache.shiro.realm.Realm; import org.apache.shiro.realm.RealmFactory; import org.apache.shiro.util.StringUtils; /** * Looks up one or more Realm instances from JNDI using specified {@link #setJndiNames jndiNames}. * * <p>This is primarily provided to support Realm instances configured in JEE and EJB environments, but will * work in any environment where {@link Realm Realm} instances are bound in JNDI instead of using * programmatic or text-based configuration. * * @since 0.9 */ public class JndiRealmFactory extends JndiLocator implements RealmFactory { Collection<String> jndiNames = null; /** * Returns the JNDI names that will be used to look up Realm(s) from JNDI. * * @return the JNDI names that will be used to look up Realm(s) from JNDI. * @see #setJndiNames(String) * @see #setJndiNames(Collection) */ public Collection<String> getJndiNames() { return jndiNames; } /** * Sets the JNDI names that will be used to look up Realm(s) from JNDI. * <p/> * The order of the collection determines the order that the Realms will be returned to the SecurityManager. * <p/> * If you find it easier to specify these names as a comma-delmited string, you may use the * {@link #setJndiNames(String)} method instead. * * @param jndiNames the JNDI names that will be used to look up Realm(s) from JNDI. * @see #setJndiNames(String) */ public void setJndiNames(Collection<String> jndiNames) { this.jndiNames = jndiNames; } /** * Specifies a comma-delimited list of JNDI names to lookup, each one corresponding to a jndi-bound * {@link Realm Realm}. The Realms will be made available to the SecurityManager in the order * they are defined. * * @param commaDelimited a comma-delimited list of JNDI names, each representing the JNDI name used to * look up a corresponding jndi-bound Realm. * @throws IllegalStateException if the specified argument is null or the empty string. */ public void setJndiNames(String commaDelimited) throws IllegalStateException { String arg = StringUtils.clean(commaDelimited); if (arg == null) { String msg = "One or more comma-delimited jndi names must be specified for the " + getClass().getName() + " to locate Realms."; throw new IllegalStateException(msg); } String[] names = StringUtils.tokenizeToStringArray(arg, ","); setJndiNames(Arrays.asList(names)); } /** * Performs the JNDI lookups for each specified {@link #getJndiNames() JNDI name} and returns all * discovered Realms in an ordered collection. * * <p>The returned Collection is in the same order as the specified * {@link #setJndiNames(java.util.Collection) jndiNames} * * @return an ordered collection of the {@link #setJndiNames(java.util.Collection) specified Realms} found in JNDI. * @throws IllegalStateException if any of the JNDI names fails to successfully look up a Realm instance. */ public Collection<Realm> getRealms() throws IllegalStateException { Collection<String> jndiNames = getJndiNames(); if (jndiNames == null || jndiNames.isEmpty()) { String msg = "One or more jndi names must be specified for the " + getClass().getName() + " to locate Realms."; throw new IllegalStateException(msg); } List<Realm> realms = new ArrayList<Realm>(jndiNames.size()); for (String name : jndiNames) { try { Realm realm = (Realm) lookup(name, Realm.class); realms.add(realm); } catch (Exception e) { throw new IllegalStateException("Unable to look up realm with jndi name '" + name + "'.", e); } } return realms.isEmpty() ? null : realms; } }