/******************************************************************************* * $Novell: DynamicGroup.java,v 1.8 2003/08/21 11:32:07 $ * * Copyright (c) 2000, 2001 Novell, Inc. All Rights Reserved. * * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND * TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE * AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS * THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO * DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE * CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS * TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF * DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR * DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS CODE. * * $name: DynamicGroup.java * * $description: The DynamicGroup.java sample demonstrates how to: * 1) create the Dynamic Group Entry cn=myDynamicGroup * in a specified container with a specified memberQueryURL * 2) read and print the values of the "member" attribute of cn=myDynamicGroup * 3) delete the dynamic group * * Notes on Dynamic Groups: * * Dynamic groups are supported in Novell eDirectory version 8.6.1 or later. * * A dynamic group is similar to a group entry, but has a search URL * attribute. Entries satisfying the search URL are considered members of * the group. The DN of each member will be returned when reading the * "member" (or its synonym "uniqueMember") attribute. * * A dynamic group is created either with objectClass="dynamicGroup" or by * adding the auxiliary class "dynamicGroupAux" to an existing group entry. * * The search URL is specified in the "memberQueryURL" attribute. * The value of "memberQueryURL" is encoded as an "LDAP URL". * * An entry may be statically added to a dynamic group by adding its DN * to the "member" (or its synonym "uniqueMember") attribute. Similarly * an entry may be statically excluded from the group by adding its DN to the * "excludedMember" attribute. These entries will be included or excluded * from the group regardless of the search URL. * * Note: at the present time, the only way to view only the static members * of a dynamic group is to delete the memberQueryURL attribute and * then read the member attribute. * * In order to provide consistent results when processing the search URL, * the authorization identity DN used to determine group membership is based * on the following criteria: * 1) If the "dgIdentity" attribute is present, its value is the identity DN. * 2) If the above is false, and if the dynamic group entry contains a * public/private key, then the DN of the group entry is the identity DN. * 3) If neither of the above are true, then the anonymous identity is the * identity DN. * * The creator of the group cannot set the "dgIdentity" attribute to a DN * to which he or she does not already have rights. The dynamic group entry * and the DN specified by dgIdentity must be on the same server. * * The "dgAllowDuplicates" attribute enables or disables the presence * of duplicate values in the "membership" attribute. The default is false. * Setting this attribute to true results in a faster search, but some values * in the "membership" attribute may be duplicates. * * The "dgTimeout" attribute determines the number of seconds to wait to get * results from another server during dynamic group member search, when the * search spans multiple servers. * * The format the search URL in the memberQueryUrl attribute is: * ldap://<base dn>??<scope>?<filter>[?[!]x-chain] * * The optional extension "x-chain" causes the server to chain to other * servers if necessary to complete the search. When present, the search * will NOT be limited to the host server. This extension should be used * carefully. The exclamation indicates it is a critical extension, and if set * the server will return an error if chaining is not supported or enabled. * * For example, to create a dynamic group consisting of all entries in the * "ou=sales,o=acme" subtree with the title "Manager", set memberQueryURL to: * "ldap://ou=sales,o=acme??sub?(title=Manager)" * ******************************************************************************/ import com.novell.ldap.*; import java.util.Enumeration; import java.util.Iterator; import java.io.UnsupportedEncodingException; public class DynamicGroup { public static void main( String[] args ) { if (args.length != 5) { System.err.println("Usage: java DynamicGroup <host name>" + " <login dn> <password> <container name>" + " <queryURL>"); System.err.println("Example: java DynamicGroup Acme.com" + " \"cn=admin, o=Acme\" secret \"o=Acme\" \n " + " ldap://ou=Sales,o=Acme??sub?(title=*Manager*)\n"); System.exit(1); } // Set LDAP version to 3 */ int ldapVersion = LDAPConnection.LDAP_V3; int ldapPort = LDAPConnection.DEFAULT_PORT; String ldapHost = args[0]; String loginDN = args[1]; String password = args[2]; String containerName = args[3]; String queryURL = args[4]; /* Construct the entry's dn using the container name from the * command line and the name of the new dynamic group entry to create. */ String dn = "cn=myDynamicGroup," + containerName; LDAPConnection lc = new LDAPConnection(); try { // connect to the server lc.connect( ldapHost, ldapPort ); // bind to the server lc.bind( ldapVersion, loginDN, password.getBytes("UTF8") ); // Adding dynamic group entry to the tree System.out.println( "\tAdding dynamic group entry..."); /* add a dynamic group entry to the directory tree in the * specified container */ addDynamicGroupEntry( lc, loginDN, dn, queryURL); /* Reading the member attribute of dynamic group entry and * printing the values */ System.out.println("\n\tReading the \"member\" " + " attribute of dynamic group ojbect ..."); searchDynamicGroupEntry ( lc, dn ); // Removing the dynamic group entry from the specified container System.out.println("\n\tDeleting dynamic group entry..."); deleteDynamicGroupEntry( lc, dn ); // disconnect with the server lc.disconnect(); } catch( LDAPException e ) { System.out.println( "Error: " + e.toString() ); } catch( UnsupportedEncodingException e ) { System.out.println( "Error: " + e.toString() ); } System.exit(0); } // add dynamic group entry public static boolean addDynamicGroupEntry ( LDAPConnection lc, String loginDN, String entryDN, String queryURL) { boolean status = true; LDAPAttributeSet attributeSet = new LDAPAttributeSet(); //The objectclass "dynamicGroup is used to create dynamic group entries attributeSet.add( new LDAPAttribute( "objectclass", "dynamicGroup" )); /* The memberQueryURL attribute describes the membership of the list * using an LDAPURL, which is defined in RFC2255 */ attributeSet.add( new LDAPAttribute( "memberQueryURL", queryURL ) ); /* Set the identity to use for the implied search. loginDN is used * as the dgIdentity in this sample. */ attributeSet.add( new LDAPAttribute( "dgIdentity", loginDN ) ); LDAPEntry newEntry = new LDAPEntry( entryDN, attributeSet ); try { lc.add( newEntry ); System.out.println("\tEntry: " + entryDN + " added successfully." ); } catch( LDAPException e ) { System.out.println( "\t\tFailed to add dynamic group entry " + entryDN); System.out.println( "Error: " + e.toString() ); status = false; } return status; } // read and print search results public static boolean searchDynamicGroupEntry ( LDAPConnection lc, String searchBase ) { boolean status = true; int searchScope = LDAPConnection.SCOPE_BASE; String[] attrList = new String[]{"member"}; String searchFilter = "(objectclass=*)"; /* Since reading members of a dynamic group could potentially involve * a significant directory search, we use a timeout. Setting * time out to 10 seconds */ LDAPSearchConstraints cons = new LDAPSearchConstraints(); cons.setTimeLimit( 10000 ) ; try { LDAPSearchResults searchResults = lc.search( searchBase, searchScope, searchFilter, attrList, // return only "member" attr false, // return attrs and values cons ); // time out value LDAPEntry nextEntry = null ; // Read and print search results. We expect only one entry */ if (( nextEntry = searchResults.next()) != null ) { LDAPAttributeSet attributeSet = nextEntry.getAttributeSet(); Iterator allAttributes = attributeSet.iterator(); if ( allAttributes.hasNext() ) { // found member(s) in this group LDAPAttribute attribute = (LDAPAttribute)allAttributes.next(); String attributeName = attribute.getName(); Enumeration allValues = attribute.getStringValues(); if( allValues != null) { while(allValues.hasMoreElements()) { String Value = (String) allValues.nextElement(); System.out.println(" " + attributeName + " : " + Value); } } } else { // no member(s) found in this group System.out.println(" No objects passed the " + " memberQueryURL filter.\n Hence, there " + " are no members in this group.\n"); } } } catch( LDAPException e ) { System.out.println( "Error: " + e.toString() ); status = false; } return status; } // delete the dynamic group entry public static boolean deleteDynamicGroupEntry( LDAPConnection lc, String deleteDN ) { boolean status = true; try { // Deletes the entry from the directory lc.delete( deleteDN ); System.out.println("\tEntry: " + deleteDN + " was deleted." ); } catch( LDAPException e ) { System.out.println( "\t\tFailed to remove dynamic group entry." ); System.out.println( "Error: " + e.toString() ); status = false; } return status; } }