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