001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2012-2014 ForgeRock AS. 015 */ 016 017package org.forgerock.opendj.examples; 018 019import java.util.Collection; 020 021import org.forgerock.opendj.ldap.Connection; 022import org.forgerock.opendj.ldap.LdapException; 023import org.forgerock.opendj.ldap.LDAPConnectionFactory; 024import org.forgerock.opendj.ldap.ModificationType; 025import org.forgerock.opendj.ldap.ResultCode; 026import org.forgerock.opendj.ldap.RootDSE; 027import org.forgerock.opendj.ldap.controls.PermissiveModifyRequestControl; 028import org.forgerock.opendj.ldap.requests.CompareRequest; 029import org.forgerock.opendj.ldap.requests.ModifyRequest; 030import org.forgerock.opendj.ldap.requests.Requests; 031import org.forgerock.opendj.ldap.responses.CompareResult; 032 033/** 034 * This command-line client demonstrates adding and removing a member from a 035 * (potentially large) static group. 036 * 037 * The client takes as arguments the host and port of the directory server, the 038 * group DN, the member DN, and whether to "add" or "del" the specified member 039 * from the group. The client uses the Permissive Modify control if it is 040 * available to avoid having to check whether the member belongs to the group or 041 * not. 042 * 043 * This client expects a group that is a <code>groupOfNames</code> such as: 044 * 045 * <pre> 046 * dn: cn=My Static Group,ou=Groups,dc=example,dc=com 047 * cn: My Static Group 048 * objectClass: groupOfNames 049 * objectClass: top 050 * ou: Groups 051 * member: uid=ahunter,ou=People,dc=example,dc=com 052 * member: uid=bjensen,ou=People,dc=example,dc=com 053 * member: uid=tmorris,ou=People,dc=example,dc=com 054 * </pre> 055 * 056 * This client connects as <code>cn=Directory Manager</code> with password 057 * <code>password</code>. Not a best practice; in real code use application 058 * specific credentials to connect, and ensure that your application has access 059 * to use the Permissive Modify control if your directory server supports it. 060 */ 061public final class UpdateGroup { 062 063 /** 064 * Connect to the directory server to update the group. 065 * 066 * @param args 067 * The command line arguments: host, port, group-dn, member-dn, 068 * {add|del} 069 */ 070 public static void main(String[] args) { 071 if (args.length != 5) { 072 printUsage(); 073 } 074 final String host = args[0]; 075 final int port = Integer.parseInt(args[1]); 076 final String groupDN = args[2]; 077 final String memberDN = args[3]; 078 final ModificationType modType = getModificationType(args[4]); 079 080 final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port); 081 Connection connection = null; 082 try { 083 connection = factory.getConnection(); 084 085 Collection<String> controls = 086 RootDSE.readRootDSE(connection).getSupportedControls(); 087 088 final String user = "cn=Directory Manager"; 089 final char[] password = "password".toCharArray(); 090 connection.bind(user, password); 091 092 // --- JCite permissive --- 093 if (controls.contains(PermissiveModifyRequestControl.OID)) { 094 095 final ModifyRequest request = Requests.newModifyRequest(groupDN) 096 .addControl(PermissiveModifyRequestControl.newControl(true)) 097 .addModification(modType, "member", memberDN); 098 connection.modify(request); 099 100 } else { 101 // --- JCite permissive --- 102 103 // --- JCite without permissive --- 104 System.out.println("Checking whether the entry with DN " 105 + memberDN + " belongs to the group with DN " + groupDN 106 + "..."); 107 final CompareRequest request = 108 Requests.newCompareRequest(groupDN, "member", memberDN); 109 CompareResult result = connection.compare(request); 110 111 if (modType == ModificationType.ADD 112 && result.getResultCode() == ResultCode.COMPARE_FALSE) { 113 System.out.println("Member does not yet belong to group." 114 + " Adding it..."); 115 final ModifyRequest addMember = 116 Requests.newModifyRequest(groupDN) 117 .addModification(modType, "member", memberDN); 118 connection.modify(addMember); 119 } 120 121 if (modType == ModificationType.DELETE 122 && result.getResultCode() == ResultCode.COMPARE_TRUE) { 123 System.out.println("Member belongs to group." 124 + " Removing it..."); 125 final ModifyRequest delMember = 126 Requests.newModifyRequest(groupDN) 127 .addModification(modType, "member", memberDN); 128 connection.modify(delMember); 129 } 130 // --- JCite without permissive --- 131 } 132 133 String op = (modType == ModificationType.ADD) ? "added to" : "deleted from"; 134 System.out.println("The entry with DN " + memberDN + " has been " 135 + op + " the group with DN " + groupDN + "."); 136 137 } catch (final LdapException e) { 138 System.err.println(e.getMessage()); 139 System.exit(e.getResult().getResultCode().intValue()); 140 return; 141 } finally { 142 if (connection != null) { 143 connection.close(); 144 } 145 } 146 } 147 148 /** 149 * Return the modification type for the update operation. 150 * @param operation Operation specified as an argument (add or del). 151 */ 152 private static ModificationType getModificationType(String operation) { 153 final boolean isAdd = "add".equalsIgnoreCase(operation); 154 if (!isAdd && !"del".equalsIgnoreCase(operation)) { 155 printUsage(); 156 } 157 return isAdd ? ModificationType.ADD : ModificationType.DELETE; 158 } 159 160 /** 161 * Print usage then exit. 162 */ 163 private static void printUsage() { 164 System.err.println("Usage: host port group-dn member-dn {add|del}"); 165 System.err.println("For example: localhost 1389 " 166 + "cn=Static,ou=Groups,dc=example,dc=com " 167 + "uid=user.5150,ou=People,dc=example,dc=com " 168 + "del"); 169 System.exit(1); 170 } 171 172 /** 173 * Constructor not used. 174 */ 175 private UpdateGroup() { 176 // Not used. 177 } 178}