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 2009-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2011-2015 ForgeRock AS. 016 */ 017 018package org.forgerock.opendj.examples; 019 020import org.forgerock.opendj.io.ASN1; 021import org.forgerock.opendj.io.ASN1Writer; 022import org.forgerock.opendj.ldap.ByteStringBuilder; 023import org.forgerock.opendj.ldap.Connection; 024import org.forgerock.opendj.ldap.DecodeOptions; 025import org.forgerock.opendj.ldap.Entry; 026import org.forgerock.opendj.ldap.LdapException; 027import org.forgerock.opendj.ldap.LDAPConnectionFactory; 028import org.forgerock.opendj.ldap.ModificationType; 029import org.forgerock.opendj.ldap.ResultCode; 030import org.forgerock.opendj.ldap.SearchScope; 031import org.forgerock.opendj.ldap.controls.GenericControl; 032import org.forgerock.opendj.ldap.controls.PreReadResponseControl; 033import org.forgerock.opendj.ldap.requests.ModifyRequest; 034import org.forgerock.opendj.ldap.requests.Requests; 035import org.forgerock.opendj.ldap.responses.Result; 036import org.forgerock.opendj.ldap.responses.SearchResultEntry; 037import org.forgerock.opendj.ldif.LDIFEntryWriter; 038 039import java.io.IOException; 040 041/** 042 * An example client application which uses 043 * {@link org.forgerock.opendj.ldap.controls.GenericControl} to pass the 044 * pre-read request control from <a href="http://tools.ietf.org/html/rfc4527" 045 * >RFC 4527 - Lightweight Directory Access Protocol (LDAP) Read Entry Controls</a>. 046 * 047 * <br>This example takes the following command line parameters: 048 * 049 * <pre> 050 * {@code <host> <port> <username> <password> <userDN>} 051 * </pre> 052 * 053 * <br>This example modifies the description attribute of an entry that 054 * you specify in the {@code <userDN>} command line parameter. 055 */ 056public final class UseGenericControl { 057 /** 058 * Main method. 059 * 060 * @param args The command line arguments: host, port, username, password, 061 * base DN, where the base DN is the root of a naming context. 062 */ 063 public static void main(final String[] args) { 064 if (args.length < 5) { 065 System.err.println("Usage: host port username password userDN"); 066 System.exit(1); 067 } 068 069 // Parse command line arguments. 070 final String hostName = args[0]; 071 final int port = Integer.parseInt(args[1]); 072 final String userName = args[2]; 073 final String password = args[3]; 074 final String userDN = args[4]; 075 076 // --- JCite --- 077 // Create an LDIF writer to write entries to stdout. 078 final LDIFEntryWriter writer = new LDIFEntryWriter(System.out); 079 080 // Connect and bind to the server. 081 final LDAPConnectionFactory factory = 082 new LDAPConnectionFactory(hostName, port); 083 Connection connection = null; 084 085 // Prepare the value for the GenericControl. 086 087 // http://tools.ietf.org/html/rfc4527#section-3.1 says: 088 // "The Pre-Read request control is a LDAP Control [RFC4511] whose 089 // controlType is 1.3.6.1.1.13.1 and whose controlValue is a BER-encoded 090 // AttributeSelection [RFC4511], as extended by [RFC3673]." 091 092 ByteStringBuilder builder = new ByteStringBuilder(); 093 ASN1Writer asn1Writer = ASN1.getWriter(builder); 094 try { 095 asn1Writer.writeStartSequence(); 096 asn1Writer.writeOctetString("description"); 097 asn1Writer.writeEndSequence(); 098 asn1Writer.flush(); 099 asn1Writer.close(); 100 } catch (Exception e) { 101 System.out.println("Failed to prepare control value: " 102 + e.getCause()); 103 System.exit(-1); 104 } 105 106 try { 107 connection = factory.getConnection(); 108 connection.bind(userName, password.toCharArray()); 109 110 // Modify the user description. 111 final ModifyRequest request = 112 Requests 113 .newModifyRequest(userDN) 114 .addModification(ModificationType.REPLACE, 115 "description", "A new description") 116 .addControl( 117 GenericControl 118 .newControl( 119 "1.3.6.1.1.13.1", 120 true, 121 builder.toByteString())); 122 final Result result = connection.modify(request); 123 124 // Display the description before and after the modification. 125 if (result.isSuccess()) { 126 final PreReadResponseControl control = result.getControl( 127 PreReadResponseControl.DECODER, new DecodeOptions() 128 ); 129 final Entry unmodifiedEntry = control.getEntry(); 130 writer.writeComment("Before modification"); 131 writer.writeEntry(unmodifiedEntry); 132 writer.flush(); 133 134 final SearchResultEntry modifiedEntry = 135 connection.searchSingleEntry( 136 userDN, 137 SearchScope.BASE_OBJECT, 138 "(objectclass=*)", 139 "description"); 140 writer.writeComment("After modification"); 141 writer.writeEntry(modifiedEntry); 142 writer.flush(); 143 } 144 145 } catch (final LdapException e) { 146 System.err.println(e.getMessage()); 147 System.exit(e.getResult().getResultCode().intValue()); 148 } catch (final IOException e) { 149 System.err.println(e.getMessage()); 150 System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue()); 151 } finally { 152 if (connection != null) { 153 connection.close(); 154 } 155 } 156 // --- JCite --- 157 } 158 159 private UseGenericControl() { 160 // Not used. 161 } 162}