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 *      Copyright 2012-2014 ForgeRock AS
024 *
025 */
026
027package org.forgerock.opendj.examples;
028
029import java.util.Collection;
030
031import org.forgerock.opendj.ldap.Connection;
032import org.forgerock.opendj.ldap.LdapException;
033import org.forgerock.opendj.ldap.LDAPConnectionFactory;
034import org.forgerock.opendj.ldap.RootDSE;
035import org.forgerock.opendj.ldap.requests.PasswordModifyExtendedRequest;
036import org.forgerock.opendj.ldap.requests.Requests;
037import org.forgerock.opendj.ldap.requests.WhoAmIExtendedRequest;
038import org.forgerock.opendj.ldap.responses.PasswordModifyExtendedResult;
039import org.forgerock.opendj.ldap.responses.Result;
040import org.forgerock.opendj.ldap.responses.WhoAmIExtendedResult;
041
042/**
043 * This command-line client demonstrates use of LDAP extended operations. The
044 * client takes as arguments the host and port for the directory server, and
045 * expects to find the entries and access control instructions as defined in <a
046 * href="http://opendj.forgerock.org/Example.ldif">Example.ldif</a>.
047 *
048 * This client connects as <code>cn=Directory Manager</code> with password
049 * <code>password</code>. Not a best practice; in real code use application
050 * specific credentials to connect, and ensure that your application has access
051 * to use the LDAP extended operations needed.
052 */
053public final class ExtendedOperations {
054
055    /**
056     * Connect to the server, and then try to use some LDAP extended operations.
057     *
058     * @param args
059     *            The command line arguments: host, port
060     */
061    public static void main(final String[] args) {
062        if (args.length != 2) {
063            System.err.println("Usage: host port");
064            System.err.println("For example: localhost 1389");
065            System.exit(1);
066        }
067        final String host = args[0];
068        final int port = Integer.parseInt(args[1]);
069
070        final LDAPConnectionFactory factory = new LDAPConnectionFactory(host, port);
071        Connection connection = null;
072
073        try {
074            connection = factory.getConnection();
075            checkSupportedExtendedOperations(connection);
076
077            final String user = "cn=Directory Manager";
078            final char[] password = "password".toCharArray();
079            connection.bind(user, password);
080
081            // Uncomment a method to run one of the examples.
082
083            // For a Cancel Extended request, see the SearchAsync example.
084            //usePasswordModifyExtendedRequest(connection);
085            // For StartTLS, see the authentication examples.
086            useWhoAmIExtendedRequest(connection);
087
088        } catch (LdapException e) {
089            System.err.println(e.getMessage());
090            System.exit(e.getResult().getResultCode().intValue());
091            return;
092        } finally {
093            if (connection != null) {
094                connection.close();
095            }
096        }
097    }
098
099    /**
100     * Use the password modify extended request.
101     *
102     * @param connection
103     *            Active connection to LDAP server containing <a
104     *            href="http://opendj.forgerock.org/Example.ldif"
105     *            >Example.ldif</a> content.
106     * @throws LdapException
107     *             Operation failed.
108     */
109    static void usePasswordModifyExtendedRequest(Connection connection) throws LdapException {
110        // --- JCite password modify ---
111        if (isSupported(PasswordModifyExtendedRequest.OID)) {
112            final String userIdentity = "u:scarter";
113            final char[] oldPassword = "sprain".toCharArray();
114            final char[] newPassword = "secret12".toCharArray();
115
116            final PasswordModifyExtendedRequest request =
117                    Requests.newPasswordModifyExtendedRequest()
118                        .setUserIdentity(userIdentity)
119                        .setOldPassword(oldPassword)
120                        .setNewPassword(newPassword);
121
122            final PasswordModifyExtendedResult result =
123                    connection.extendedRequest(request);
124            if (result.isSuccess()) {
125                System.out.println("Changed password for " + userIdentity);
126            } else {
127                System.err.println(result.getDiagnosticMessage());
128            }
129        } else {
130            System.err.println("PasswordModifyExtendedRequest not supported");
131        }
132        // --- JCite password modify ---
133    }
134
135    /**
136     * Use the Who Am I? extended request.
137     *
138     * @param connection Active connection to LDAP server containing <a
139     *            href="http://opendj.forgerock.org/Example.ldif"
140     *            >Example.ldif</a> content.
141     * @throws LdapException
142     *             Operation failed.
143     */
144    static void useWhoAmIExtendedRequest(Connection connection) throws LdapException {
145        // --- JCite who am I ---
146        if (isSupported(WhoAmIExtendedRequest.OID)) {
147
148            final String name = "uid=bjensen,ou=People,dc=example,dc=com";
149            final char[] password = "hifalutin".toCharArray();
150
151            final Result result = connection.bind(name, password);
152            if (result.isSuccess()) {
153
154                final WhoAmIExtendedRequest request =
155                        Requests.newWhoAmIExtendedRequest();
156                final WhoAmIExtendedResult extResult =
157                        connection.extendedRequest(request);
158
159                if (extResult.isSuccess()) {
160                    System.out.println("Authz ID: "  + extResult.getAuthorizationID());
161                }
162            }
163        } else {
164            System.err.println("WhoAmIExtendedRequest not supported");
165        }
166        // --- JCite who am I ---
167    }
168
169    // --- JCite check support ---
170    /**
171     * Controls supported by the LDAP server.
172     */
173    private static Collection<String> extendedOperations;
174
175    /**
176     * Populate the list of supported LDAP extended operation OIDs.
177     *
178     * @param connection
179     *            Active connection to the LDAP server.
180     * @throws LdapException
181     *             Failed to get list of extended operations.
182     */
183    static void checkSupportedExtendedOperations(Connection connection) throws LdapException {
184        extendedOperations = RootDSE.readRootDSE(connection)
185                .getSupportedExtendedOperations();
186    }
187
188    /**
189     * Check whether an extended operation is supported. Call
190     * {@code checkSupportedExtendedOperations} first.
191     *
192     * @param extendedOperation
193     *            Check support for this extended operation, provided by OID.
194     * @return True if the control is supported.
195     */
196    static boolean isSupported(final String extendedOperation) {
197        return extendedOperations != null && extendedOperations.contains(extendedOperation);
198    }
199    // --- JCite check support ---
200
201    /**
202     * Constructor not used.
203     */
204    private ExtendedOperations() {
205        // Not used.
206    }
207}