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}