View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions Copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2009-2010 Sun Microsystems, Inc.
15   * Portions Copyright 2011-2015 ForgeRock AS.
16   */
17  
18  package org.forgerock.opendj.examples;
19  
20  import org.forgerock.opendj.io.ASN1;
21  import org.forgerock.opendj.io.ASN1Writer;
22  import org.forgerock.opendj.ldap.ByteStringBuilder;
23  import org.forgerock.opendj.ldap.Connection;
24  import org.forgerock.opendj.ldap.DecodeOptions;
25  import org.forgerock.opendj.ldap.Entry;
26  import org.forgerock.opendj.ldap.LdapException;
27  import org.forgerock.opendj.ldap.LDAPConnectionFactory;
28  import org.forgerock.opendj.ldap.ModificationType;
29  import org.forgerock.opendj.ldap.ResultCode;
30  import org.forgerock.opendj.ldap.SearchScope;
31  import org.forgerock.opendj.ldap.controls.GenericControl;
32  import org.forgerock.opendj.ldap.controls.PreReadResponseControl;
33  import org.forgerock.opendj.ldap.requests.ModifyRequest;
34  import org.forgerock.opendj.ldap.requests.Requests;
35  import org.forgerock.opendj.ldap.responses.Result;
36  import org.forgerock.opendj.ldap.responses.SearchResultEntry;
37  import org.forgerock.opendj.ldif.LDIFEntryWriter;
38  
39  import java.io.IOException;
40  
41  /**
42   * An example client application which uses
43   * {@link org.forgerock.opendj.ldap.controls.GenericControl} to pass the
44   * pre-read request control from <a href="http://tools.ietf.org/html/rfc4527"
45   * >RFC 4527 - Lightweight Directory Access Protocol (LDAP) Read Entry Controls</a>.
46   *
47   * <br>This example takes the following command line parameters:
48   *
49   * <pre>
50   *  {@code <host> <port> <username> <password> <userDN>}
51   * </pre>
52   *
53   * <br>This example modifies the description attribute of an entry that
54   * you specify in the {@code <userDN>} command line parameter.
55   */
56  public final class UseGenericControl {
57      /**
58       * Main method.
59       *
60       * @param args The command line arguments: host, port, username, password,
61       *             base DN, where the base DN is the root of a naming context.
62       */
63      public static void main(final String[] args) {
64          if (args.length < 5) {
65              System.err.println("Usage: host port username password userDN");
66              System.exit(1);
67          }
68  
69          // Parse command line arguments.
70          final String hostName = args[0];
71          final int port = Integer.parseInt(args[1]);
72          final String userName = args[2];
73          final String password = args[3];
74          final String userDN = args[4];
75  
76          // --- JCite ---
77          // Create an LDIF writer to write entries to stdout.
78          final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
79  
80          // Connect and bind to the server.
81          final LDAPConnectionFactory factory =
82                  new LDAPConnectionFactory(hostName, port);
83          Connection connection = null;
84  
85          // Prepare the value for the GenericControl.
86  
87          // http://tools.ietf.org/html/rfc4527#section-3.1 says:
88          // "The Pre-Read request control is a LDAP Control [RFC4511] whose
89          // controlType is 1.3.6.1.1.13.1 and whose controlValue is a BER-encoded
90          // AttributeSelection [RFC4511], as extended by [RFC3673]."
91  
92          ByteStringBuilder builder = new ByteStringBuilder();
93          ASN1Writer asn1Writer = ASN1.getWriter(builder);
94          try {
95              asn1Writer.writeStartSequence();
96              asn1Writer.writeOctetString("description");
97              asn1Writer.writeEndSequence();
98              asn1Writer.flush();
99              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 }