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}