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 java.io.IOException;
031
032import org.forgerock.opendj.ldap.Connection;
033import org.forgerock.opendj.ldap.LdapException;
034import org.forgerock.opendj.ldap.LDAPConnectionFactory;
035import org.forgerock.opendj.ldap.ResultCode;
036import org.forgerock.opendj.ldap.SearchScope;
037import org.forgerock.opendj.ldap.controls.GenericControl;
038import org.forgerock.opendj.ldap.requests.Requests;
039import org.forgerock.opendj.ldap.requests.SearchRequest;
040import org.forgerock.opendj.ldap.responses.SearchResultEntry;
041import org.forgerock.opendj.ldap.responses.SearchResultReference;
042import org.forgerock.opendj.ldif.ConnectionEntryReader;
043import org.forgerock.opendj.ldif.LDIFEntryWriter;
044
045/**
046 * An example client application which searches Microsoft Active Directory
047 * synchronously, using {@link GenericControl} to pass the <a
048 * href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms676877(v=vs.85).aspx"
049 * >Microsoft LDAP Notification control</a>.
050 *
051 * <p>This example is a near copy of {@link Search}, but works only with
052 * directory servers like Active Directory that support the control with OID
053 * 1.2.840.113556.1.4.528.
054 *
055 * <p>This example takes the following command line parameters:
056 *
057 * <pre>
058 *  {@code <host> <port> <username> <password> <baseDN>}
059 * </pre>
060 *
061 * <p>The {@code baseDN} must be the root of a naming context in this example.
062 */
063public final class GetADChangeNotifications {
064    /**
065     * Main method.
066     *
067     * @param args
068     *            The command line arguments: host, port, username, password,
069     *            base DN, where the base DN is the root of a naming context.
070     */
071    public static void main(final String[] args) {
072        if (args.length < 5) {
073            System.err.println("Usage: host port username password baseDN");
074            System.exit(1);
075        }
076
077        // Parse command line arguments.
078        final String hostName = args[0];
079        final int port = Integer.parseInt(args[1]);
080        final String userName = args[2];
081        final String password = args[3];
082        final String baseDN = args[4];
083
084        // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa772153(v=vs.85).aspx
085        // --- JCite ---
086        final SearchScope scope = SearchScope.WHOLE_SUBTREE;
087        final String filter = "(objectclass=*)";
088        final String[] attributes = {
089            "objectclass", "objectGUID", "isDeleted", "uSNChanged"
090        };
091
092        // Create an LDIF writer which will write the search results to stdout.
093        final LDIFEntryWriter writer = new LDIFEntryWriter(System.out);
094
095        // Connect and bind to the server.
096        final LDAPConnectionFactory factory =
097                new LDAPConnectionFactory(hostName, port);
098        Connection connection = null;
099
100        try {
101            connection = factory.getConnection();
102            connection.bind(userName, password.toCharArray());
103
104            // Read the entries and output them as LDIF.
105            final SearchRequest request =
106                    Requests
107                            .newSearchRequest(baseDN, scope, filter, attributes)
108                            .addControl(
109                                    GenericControl
110                                            .newControl(
111                                                    "1.2.840.113556.1.4.528",
112                                                    true));
113            final ConnectionEntryReader reader = connection.search(request);
114            while (reader.hasNext()) {
115                if (!reader.isReference()) {
116                    final SearchResultEntry entry = reader.readEntry();
117                    writer.writeComment("Search result entry: " + entry.getName());
118                    writer.writeEntry(entry);
119                    writer.flush();
120                } else {
121                    final SearchResultReference ref = reader.readReference();
122
123                    // Got a continuation reference.
124                    writer.writeComment("Search result reference: " + ref.getURIs());
125                }
126            }
127        } catch (final LdapException e) {
128            System.err.println(e.getMessage());
129            System.exit(e.getResult().getResultCode().intValue());
130        } catch (final IOException e) {
131            System.err.println(e.getMessage());
132            System.exit(ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue());
133        } finally {
134            if (connection != null) {
135                connection.close();
136            }
137        }
138        // --- JCite ---
139    }
140
141    private GetADChangeNotifications() {
142        // Not used.
143    }
144}