All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jndi.ldap.obj.GroupOfNames Maven / Gradle / Ivy

/*
 * Copyright (c) 2003, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.jndi.ldap.obj;

import com.sun.enterprise.security.GroupPrincipal;
import com.sun.jndi.ldap.LdapURL;

import java.security.Principal;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.NoSuchElementException;
import java.util.Set;

import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.LdapContext;
import javax.naming.spi.NamingManager;

/**
 * A representation of the LDAP groupOfNames object class.
 * This is a static group: its members are listed in the group's member
 * LDAP attribute.
 * 

* Note that when a GroupOfNames object is created by the application * program then most of its methods throw {@link IllegalStateException} * until the program binds the object in the directory. However, when a * GroupOfNames object is returned to the application program then the * object is already bound in the directory and its methods function normally. *

* A GroupOfNames instance is not synchronized against concurrent * multithreaded access. Multiple threads trying to access and modify a * GroupOfNames should lock the object. *

* In order to bind a GroupOfNames object in the directory, the * following LDAP object class definition (RFC 2256) must be supported in the * directory schema: *

 *     ( 2.5.6.9 NAME 'groupOfNames'
 *        SUP top
 *        STRUCTURAL
 *        MUST ( member $
 *               cn )
 *        MAY ( businessCategory $
 *              seeAlso $
 *              owner $
 *              ou $
 *              o $
 *              description ) )
 * 
* See * {@link javax.naming.directory.DirContext#bind(javax.naming.Name, * java.lang.Object, javax.naming.directory.Attributes) DirContext.bind} * for details on binding an object in the directory. *

* The following code sample shows how the class may be used: *

 *
 *     // set the java.naming.factory.object property
 *     env.put(Context.OBJECT_FACTORIES,
 *         "com.sun.jndi.ldap.obj.LdapGroupFactory");
 *
 *     // set the java.naming.factory.state property
 *     env.put(Context.STATE_FACTORIES,
 *         "com.sun.jndi.ldap.obj.LdapGroupFactory");
 *
 *     // create an initial context using the supplied environment properties
 *     DirContext ctx = new InitialDirContext(env);
 *
 *     // create a set of members
 *     Set members = new HashSet();
 *     members.add("cn=bill,ou=people");
 *     members.add("cn=ben,ou=people");
 *     members.add("cn=sysadmins,ou=groups");
 *     Group administrators = new GroupOfNames(members);
 *
 *     // bind the group in the directory
 *     ctx.bind("cn=administrators,ou=groups", administrators);
 *
 *     // list all of the group's members
 *     listMembers(administrators);
 *     ...
 *
 *
 *     // list the members of a group (subgroups are expanded, by default)
 *     void listMembers(Group group) {
 *         for (Enumeration members = group.members();
 *                 members.hasMoreElements(); ) {
 *             Object object = members.nextElement();
 *             if (object instanceof Group) {
 *                 System.out.println("+" + ((Group) object).getName());
 *             } else if (object instanceof Principal) {
 *                 System.out.println(" " + ((Principal) object).getName());
 *             }
 *          }
 *      }
 *
 * 
* * @author Vincent Ryan */ public class GroupOfNames implements GroupPrincipal { private static final boolean debug = false; private static final String OBJECT_CLASS = "groupOfNames"; private static final String MEMBER_ATTR_ID = "member"; private static final String MEMBER_FILTER_EXPR = "(member={0})"; private static final String EXPAND_GROUP = "com.sun.jndi.ldap.obj.expandGroup"; private static final Attribute OBJECT_CLASS_ATTR = new BasicAttribute("objectClass", "top"); static { OBJECT_CLASS_ATTR.add(OBJECT_CLASS); } private static final SearchControls BASE_SEARCH_NO_ATTRS = new SearchControls(); static { BASE_SEARCH_NO_ATTRS.setSearchScope(SearchControls.OBJECT_SCOPE); BASE_SEARCH_NO_ATTRS.setReturningAttributes(new String[0]); // no attrs } private boolean objectIsBound; private boolean expandGroup = true; private Attributes attributes = null; private Attribute memberAttr = null; private String memberAttrId; private String memberFilterExpr; private final Object[] filterArgs = new Object[1]; private final ModificationItem[] modification = new ModificationItem[1]; private String groupDN = null; private String bindDN = null; private DirContext rootCtx = null; private DirContext ctx = null; private DirContext bindCtx = null; private Name name = null; private Name bindName = null; private Hashtable env = null; /** * Create an empty group object. *

* Note that the newly constructed object does not represent a group in * the directory until it is bound by using * {@link javax.naming.directory.DirContext#bind(javax.naming.Name, * java.lang.Object, javax.naming.directory.Attributes) DirContext.bind}. */ public GroupOfNames() { if (debug) { System.out.println("[debug] constructing an empty group"); } initializeState(OBJECT_CLASS_ATTR, MEMBER_ATTR_ID, MEMBER_FILTER_EXPR, null); } /** * Create a group object with an initial set of members. *

* Note that the newly constructed object does not represent a group in * the directory until it is bound by using * {@link javax.naming.directory.DirContext#bind(javax.naming.Name, * java.lang.Object, javax.naming.directory.Attributes) DirContext.bind}. * * @param members The set of initial members. It may be null. * Each element is of class {@link String} or * {@link java.security.Principal}. */ public GroupOfNames(Set members) { if (debug) { System.out.println("[debug] constructing a group"); } initializeState(OBJECT_CLASS_ATTR, MEMBER_ATTR_ID, MEMBER_FILTER_EXPR, members); } /** * Create a group object. * This method is called by {@link GroupOfUniqueNames}. * * @param objectClass The LDAP objectClass attribute. * @param memberAttrId The LDAP attribute ID which identifies the members. * @param memberfilterExpr The filter expression used to find a member. * @param members The set of initial members. It may be null. */ // package private (used by GroupOfUniqueNames) GroupOfNames(Attribute objectClass, String memberAttrId, String memberFilterExpr, Set members) { initializeState(objectClass, memberAttrId, memberFilterExpr, members); } /** * Create a group object from its entry in the directory. * This method is called by {@link GroupOfUniqueNames}. * * @param objectClass The LDAP objectClass attribute. * @param memberAttrId The LDAP attribute ID which identifies the members. * @param memberfilterExpr The filter expression used to find a member. * @param members The set of initial members. It may be null. * @param groupDN The group's distinguished name. * @param name The group's LDAP distinguished name. * @param ctx An LDAP context. * @param name The group's name relative to the context. * @param env The context's environment properties. * @param attributes The group's LDAP attributes. */ // package private (used by GroupOfUniqueNames) GroupOfNames(Attribute objectClass, String memberAttrId, String memberFilterExpr, Set members, String groupDN, DirContext ctx, Name name, Hashtable env, Attributes attributes) { initializeState(objectClass, memberAttrId, memberFilterExpr, members); initializeBoundState(groupDN, ctx, name, env, attributes); } /** * Create a group object from its entry in the directory. * This method is called by {@link LdapGroupFactory}. * * @param groupDN The group's distinguished name. * @param ctx An LDAP context. * @param name The group's name relative to the context. * @param env The context's environment properties. * @param attributes The group's LDAP attributes. * @return Object The new object instance. */ // package private (used by LdapGroupFactory) static Object getObjectInstance(String groupDN, DirContext ctx, Name name, Hashtable env, Attributes attributes) { if (debug) { System.out.println("[debug] creating a group named: " + groupDN); } return new GroupOfNames(OBJECT_CLASS_ATTR, MEMBER_ATTR_ID, MEMBER_FILTER_EXPR, null, groupDN, ctx, name, env, attributes); } /** * Adds a member to the group. * Performs an LDAP modify to add the member. * * @param member The name of the member to be added. * @return boolean true if the addition was successful; false otherwise. * @throws IllegalStateException The exception is thrown if the * group does not represent a group in the directory. */ public boolean addMember(Principal member) { try { return addMember(member.getName()); } catch (NamingException e) { if (debug) { System.out.println("[debug] error adding the member: " + e); } return false; } } /** * Adds a member to the group. * Performs an LDAP modify to add the member. * * @param dn The distinguished name (RFC 2253) of the member to be added. * @return boolean true if the addition was successful; false otherwise. * @throws NamingException The exception is thrown if an error occurs while * performing LDAP modify. * @throws IllegalStateException The exception is thrown if the * group does not represent a group in the directory. */ public boolean addMember(String dn) throws NamingException { if (! isBound()) { throw new IllegalStateException(); } if (debug) { System.out.println("[debug] adding the member: " + dn); } return modifyMember(dn, DirContext.ADD_ATTRIBUTE); } /** * Checks if the supplied name is a member of the group. * Performs LDAP searches to determine membership. *

* By default, subgroups are also checked. * As subgroup expansion is potentially an expensive activity the feature * may be disabled by setting the environment property * "com.sun.jndi.ldap.obj.expandGroup" * to the string value "false". * * @param member The name of the member to be checked. * @return boolean true if membership is confirmed; false otherwise. * @throws IllegalStateException The exception is thrown if the * group does not represent a group in the directory. */ @Override public boolean isMember(Principal member) { try { return isMember(member.getName()); } catch (NamingException e) { if (debug) { System.out.println("[debug] error testing for membership: " + e); } return false; } } /** * Checks if the supplied name is a member of the group. * Performs LDAP searches to determine membership. *

* By default, subgroups are also checked. * As subgroup expansion is potentially an expensive activity the feature * may be disabled by setting the environment property * "com.sun.jndi.ldap.obj.expandGroup" * to the string value "false". * * @param dn The distinguished name (RFC 2253) of the member to be checked. * @return boolean true if membership is confirmed; false otherwise. * @throws NamingException The exception is thrown if an error occurs while * performing LDAP search. * @throws IllegalStateException The exception is thrown if the * group does not represent a group in the directory. */ public boolean isMember(String dn) throws NamingException { if (! isBound()) { throw new IllegalStateException(); } if (debug) { System.out.println("[debug] checking if \"" + dn + "\" is a member"); } // Check cache if (memberAttr != null && memberAttr.contains(dn)) { return true; } // Check directory group filterArgs[0] = dn; NamingEnumeration results = ctx.search(name, memberFilterExpr, filterArgs, BASE_SEARCH_NO_ATTRS); // Membership is confirmed if any results are returned if (results != null && results.hasMore()) { results.close(); // cleanup return true; } // Check directory subgroups if (expandGroup) { return isSubgroupMember(dn); } return false; } /** * Returns the members of the group. * Performs LDAP searches to retrieve the members. *

* By default, subgroups and their members are also included. * As subgroup expansion is potentially an expensive activity the feature * may be disabled by setting the environment property * "com.sun.jndi.ldap.obj.expandGroup" * to the string value "false". When the feature is disabled only the * group's direct members are returned. * * @return Enumeration The list of members of the group. * When only the {@link LdapGroupFactory} object factory is active * then each element in the enumeration is of class * {@link com.sun.enterprise.security.GroupPrincipal} or * {@link java.security.Principal}. However, when additional * object factories are active then the enumeration may contain * elements of a different class. * @throws IllegalStateException The exception is thrown if the * group does not represent a group in the directory. */ @Override public Enumeration members() { if (!isBound()) { throw new IllegalStateException(); } if (debug) { System.out.println("[debug] enumerating the members"); } try { // Retrieve the group's member attribute unless already cached if ((memberAttr != null) || (memberAttr = ctx.getAttributes(name, new String[] {memberAttrId}).get(memberAttrId)) != null) { return new Members(memberAttr.getAll()); } } catch (NamingException e) { if (debug) { System.out.println("[debug] error enumerating the members: " + e); } // ignore } return new Members(); // empty } /** * Removes a member from the group. * Performs an LDAP modify to remove the member. * * @param member The name of the member to be removed. * @return boolean true if the removal was successful; false otherwise. * @throws IllegalStateException The exception is thrown if the * group does not represent a group in the directory. */ public boolean removeMember(Principal member) { try { return removeMember(member.getName()); } catch (NamingException e) { if (debug) { System.out.println("[debug] error removing the member: " + e); } return false; } } /** * Removes a member from the group. * Performs an LDAP modify to remove the member. * * @param dn The distinguished name (RFC 2253) of the member to be removed. * @return boolean true if the removal was successful; false otherwise. * @throws NamingException The exception is thrown if an error occurs while * performing LDAP modify. * @throws IllegalStateException The exception is thrown if the * group does not represent a group in the directory. */ public boolean removeMember(String dn) throws NamingException { if (!isBound()) { throw new IllegalStateException(); } if (debug) { System.out.println("[debug] removing the member: " + dn); } return modifyMember(dn, DirContext.REMOVE_ATTRIBUTE); } /** * Retrieves the distinguished name of the group. * * @return String The distinguished name of the group. * @throws IllegalStateException The exception is thrown if the * group does not represent a group in the directory. */ @Override public String getName() { if (!isBound()) { throw new IllegalStateException(); } return groupDN; } /** * Sets the distinguished name of the group. * This method is called by {@link LdapGroupFactory}. * * @param groupDN The group's distinguished name. * @param ctx An LDAP context. * @param name The group's name relative to the context. */ // package private (used by LdapGroupFactory) void setName(String groupDN, DirContext ctx, Name name) { bindDN = groupDN; bindCtx = ctx; bindName = name; } /** * Creates a string representation of the group. * * @return String A string listing the distinguished name of the group and * the contents of the group's attribute set. See * {@link javax.naming.directory.BasicAttributes#toString()} * for details. The name is omitted if the group is not bound in * the directory and null is returned if no attributes are * available. */ @Override public String toString() { isBound(); // refresh attributes (if necessary) if (groupDN != null) { StringBuffer buffer = new StringBuffer(); buffer.append("{name: ").append(groupDN).append("}"); if (attributes != null) { buffer.append(attributes.toString()); } return buffer.toString(); } else { return attributes == null ? "" : attributes.toString(); } } /** * Retrieves the group's attributes. * This method is called by {@link LdapGroupFactory}. * * @return Attribute The group's attributes. */ // package private (used by LdapGroupFactory) Attributes getAttributes() { return attributes; } /** * Determines whether the supplied LDAP objectClass attribute matches that * of the group. A match occurs if the argument contains the value * "GroupOfNames". * * @param objectClass The non-null objectClass attribute to check against. * @return true if the objectClass attributes match; false otherwise. */ // package private (used by LdapGroupFactory) static boolean matches(Attribute objectClass) { try { for (Enumeration values = objectClass.getAll(); values.hasMoreElements();) { if (OBJECT_CLASS.equalsIgnoreCase((String) values.nextElement())) { return true; } } } catch (NamingException e) { if (debug) { System.out.println("[debug] error matching objectClass: " + e); } // ignore } return false; } /** * Determines whether the group object is bound in the directory. * * A group object is considered to be bound in the directory when * each of the values of its objectClass attribute match those of * an object in the directory having this group's distinguished name. * * @return true if the object is bound; false otherwise. */ private boolean isBound() { if (objectIsBound) { return true; } else if (bindCtx != null && bindName != null && attributes != null) { try { // Retrieve the group's attributes Attributes bindAttrs = bindCtx.getAttributes(bindName); Attribute bindObjectClass = bindAttrs.get("objectClass"); // Check whether the objectClass attributes match if (bindObjectClass != null && bindObjectClass.equals(attributes.get("objectClass"))) { // Set the group's bound state initializeBoundState(bindDN, bindCtx, bindName, env, bindAttrs); return true; } } catch (NameNotFoundException e) { if (debug) { System.out.println("[debug] object is not bound: " + e); } // ignore } catch (NamingException e) { if (debug) { System.out.println("[debug] error checking if bound: " + e); } // ignore } // Reset state to unbound bindDN = null; bindCtx = null; bindName = null; } return false; } /** * Releases the naming context created by this group. * Closes the root naming context if one had been created. * * @throws NamingException The exception is thrown if a problem is * encountered while closing the naming context. */ public void close() throws NamingException { if (rootCtx != null && rootCtx != ctx) { rootCtx.close(); rootCtx = null; } } /** * Initialize the group's state when unbound. */ private void initializeState(Attribute objectClass, String memberAttrId, String memberFilterExpr, Set members) { objectIsBound = false; this.memberAttrId = memberAttrId; this.memberFilterExpr = memberFilterExpr; // initialize the group's attribute set. attributes = new BasicAttributes(true); attributes.put(objectClass); if (members != null && (!members.isEmpty())) { memberAttr = new BasicAttribute(memberAttrId); for (Object object : members) { if (object instanceof Principal) { memberAttr.add(((Principal) object).getName()); } else { memberAttr.add(object); } } attributes.put(memberAttr); } } /** * Initialize the group's state when bound. */ private void initializeBoundState(String groupDN, DirContext ctx, Name name, Hashtable env, Attributes attributes) { objectIsBound = true; this.groupDN = groupDN; this.ctx = ctx; this.name = name; this.env = env; if (env == null && ctx != null) { try { this.env = ctx.getEnvironment(); } catch (NamingException e) { // ignore } } if (env != null) { String expandGroup = (String) env.get(EXPAND_GROUP); if ("false".equalsIgnoreCase(expandGroup)) { this.expandGroup = false; } } if (attributes != null) { this.attributes = attributes; memberAttr = attributes.get(memberAttrId); } } /** * Add or remove a value from the member attribute. */ private boolean modifyMember(String member, int mod_op) throws NamingException { Attribute memberAttr = new BasicAttribute(memberAttrId, member); modification[0] = new ModificationItem(mod_op, memberAttr); ctx.modifyAttributes(name, modification); this.memberAttr = null; // invalidate the cache return true; } /** * Checks if the supplied name is a member of any subgroups. * All the members are retrieved and any subgroups are explored. */ private boolean isSubgroupMember(String dn) throws NamingException { for (NamingEnumeration members = (NamingEnumeration) members(); members.hasMore();) { Object obj = members.next(); if (obj instanceof GroupOfNames && ((GroupOfNames) obj).isMember(dn)) { members.close(); // cleanup return true; } else if (obj instanceof GroupOfURLs && ((GroupOfURLs) obj).isMember(dn)) { members.close(); // cleanup return true; } } return false; } /** * Generate environment properties suitable for the root context using * the supplied set of properties. The following properties are modified * if necessary: *

    *
  • java.naming.provider.url property: * trim any components after hostname/port. * (identifies the root context). *
* * @param env A set of environment properties. It is cloned only when a * modification is necessary. * @return A set of environment properties suitable for the root context. */ // package private (used by GroupOfURLs) static Hashtable generateRootContextProperties(Hashtable env) { String url = null; if (env != null) { if ((url = (String) env.get(Context.PROVIDER_URL)) != null) { try { // java.net.URI is cleaner but depends on J2SE v 1.4 LdapURL ldapUrl = new LdapURL(url); String dn = ldapUrl.getDN(); // check if a non-empty DN is present if (dn != null && dn.length() > 0) { String host = ldapUrl.getHost(); int port = ldapUrl.getPort(); url = "ldap://" + ((host != null) ? host : "") + ((port != -1) ? (":" + port) : ""); } else { url = null; // reset flag } } catch (NamingException e) { throw new IllegalArgumentException(url); } } // only clone if making mods if (url != null) { env = (Hashtable) env.clone(); env.put(Context.PROVIDER_URL, url); } } return env; } /** * The members of a static group. */ class Members implements NamingEnumeration { private NamingEnumeration memberDNs = null; private final boolean expandSubgroups; private ArrayList subgroups = null; private NamingEnumeration subgroupMembers = null; /** * Empty members object derived from a static group. */ Members() { if (debug) { System.out.println("[debug] constructing an empty GroupOfNames.Members object"); } expandSubgroups = expandGroup; // GroupOfNames.expandGroup } /** * Members object derived from a static group. */ Members(NamingEnumeration memberDNs) { if (debug) { System.out.println("[debug] constructing a GroupOfNames.Members object"); } this.memberDNs = memberDNs; expandSubgroups = expandGroup; // GroupOfNames.expandGroup } /** * Check if the group has more members. * * @return true if the group has another member. */ @Override public boolean hasMoreElements() { try { return hasMore(); } catch (NamingException e) { if (debug) { System.out.println("[debug] error checking for more members: " + e); } return false; } } /** * Check if the group has more members. * * @return true if the group has another member. * @throws NamingException If a problem is encountered while checking * whether the group has any more members. */ @Override public boolean hasMore() throws NamingException { if (memberDNs == null) { return false; // empty } if (memberDNs.hasMore()) { return true; } // Check subgroups if (expandSubgroups && subgroups != null) { if (subgroupMembers == null && (! subgroups.isEmpty())) { // Retrieve the first subgroup's members subgroupMembers = (NamingEnumeration)((GroupPrincipal)subgroups.remove(0)).members(); } if (null != subgroupMembers && subgroupMembers.hasMore()) { return true; } else if (! subgroups.isEmpty()) { // Retrieve the next subgroup's members subgroupMembers = (NamingEnumeration)((GroupPrincipal)subgroups.remove(0)).members(); return subgroupMembers.hasMore(); } } return false; } /** * Retrieve the next member of the group. * Some members may themselves be groups. Such a member is returned as * an object of class {@link com.sun.enterprise.security.GroupPrincipal}. *

* Note that in order to determine whether a member is itself a group * this method reads each member's LDAP entry. As this is potentially an * expensive activity the feature may be disabled by setting the * environment property * "com.sun.jndi.ldap.obj.expandGroup" * to the string value "false". When the feature is * disabled then an object of class {@link java.security.Principal} * is returned. By default, the feature is enabled. * * @return The next member of the group. * When only the {@link LdapGroupFactory} object factory is active * then an object of class * {@link java.security.Principal} or * {@link com.sun.enterprise.security.GroupPrincipal} is returned. * However, when additional object factories are active then an * object of a different class may be returned. * @throws NoSuchElementException If no more members exist or if a * {@link javax.naming.NamingException} was encountered while * retrieving the next element. */ @Override public Object nextElement() { try { return next(); } catch (NamingException e) { // Exception.initCause is cleaner but depends on J2SE v 1.4 throw new NoSuchElementException(e.toString()); } } /** * Retrieve the next member of the group. * Some members may themselves be groups. Such a member is returned as * an object of class {@link com.sun.enterprise.security.GroupPrincipal}. *

* Note that in order to determine whether a member is itself a group * this method reads each member's LDAP entry. As this is potentially an * expensive activity the feature may be disabled by setting the * environment property * "com.sun.jndi.ldap.obj.expandGroup" * to the string value "false". When the feature is * disabled then an object of class {@link java.security.Principal} * is returned. By default, the feature is enabled. * * @return The next member of the group. * When only the {@link LdapGroupFactory} object factory is active * then an object of class * {@link java.security.Principal} or * {@link com.sun.enterprise.security.GroupPrincipal} is returned. * However, when additional object factories are active then an * object of a different class may be returned. * @throws NamingException If a problem is encountered while retrieving the * next member of the group. * @throws NoSuchElementException If no more members exist. */ @Override public Object next() throws NamingException { if (memberDNs == null) { throw new NoSuchElementException(); // empty } String memberDN = null; try { if (memberDNs.hasMore()) { memberDN = (String)memberDNs.next(); // Skip lookup when expandGroup=false if (! expandGroup) { return new LdapPrincipal(memberDN); } // Create the root context if (rootCtx == null) { rootCtx = getRootContext(); } // Perform the lookup from the root context Object object = rootCtx.lookup(new CompositeName().add(memberDN)); if (object instanceof GroupPrincipal) { if (expandSubgroups) { if (subgroups == null) { subgroups = new ArrayList(); } subgroups.add(object); } // Subgroups are members too return object; } else if (object instanceof DirContext) { ((DirContext)object).close(); // cleanup return new LdapPrincipal(memberDN); } else { return object; // additional object factories are active } } } catch (NameNotFoundException e) { // Cannot find the member's LDAP entry so return an LdapPrincipal return new LdapPrincipal(memberDN); } // Check subgroups if (expandSubgroups && subgroups != null) { if (subgroupMembers == null && (!subgroups.isEmpty())) { // Retrieve the first subgroup's members subgroupMembers = (NamingEnumeration) ((GroupPrincipal) subgroups.remove(0)).members(); } if (null != subgroupMembers && subgroupMembers.hasMore()) { return subgroupMembers.next(); } else if (!subgroups.isEmpty()) { // Retrieve the next subgroup's members subgroupMembers = (NamingEnumeration) ((GroupPrincipal) subgroups.remove(0)).members(); return subgroupMembers.next(); } } throw new NoSuchElementException(); } /** * Closes the enumeration and releases its resources. * * @throws NamingException If a problem is encountered while * closing the enumeration. */ @Override public void close() throws NamingException { if (subgroupMembers != null) { subgroupMembers.close(); // cleanup } } private DirContext getRootContext() throws NamingException { DirContext rootCtx = null; // test for the root of the namespace (the empty name) if (ctx.getNameInNamespace().length() == 0) { rootCtx = ctx; // context is already a root context } else { // Make properties suitable for the root context env = generateRootContextProperties(env); rootCtx = (DirContext) NamingManager.getInitialContext(env); // Propagate any context request controls (to rootCtx) if (ctx instanceof LdapContext) { ((LdapContext) rootCtx).setRequestControls(((LdapContext) ctx).getRequestControls()); } } return rootCtx; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy