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.FileInputStream;
031import java.io.IOException;
032
033import javax.net.ssl.SSLContext;
034
035import org.forgerock.opendj.ldap.Connections;
036import org.forgerock.opendj.ldap.LdapException;
037import org.forgerock.opendj.ldap.KeyManagers;
038import org.forgerock.opendj.ldap.LDAPClientContext;
039import org.forgerock.opendj.ldap.LDAPListener;
040import org.forgerock.opendj.ldap.LDAPListenerOptions;
041import org.forgerock.opendj.ldap.MemoryBackend;
042import org.forgerock.opendj.ldap.ResultCode;
043import org.forgerock.opendj.ldap.SSLContextBuilder;
044import org.forgerock.opendj.ldap.ServerConnection;
045import org.forgerock.opendj.ldap.ServerConnectionFactory;
046import org.forgerock.opendj.ldap.TrustManagers;
047import org.forgerock.opendj.ldif.LDIFEntryReader;
048
049/**
050 * An LDAP directory server which exposes data contained in an LDIF file. This
051 * is implementation is very simple and is only intended as an example:
052 * <ul>
053 * <li>It does not support StartTLS
054 * <li>It does not support Abandon or Cancel requests
055 * <li>Very basic authentication and authorization support.
056 * </ul>
057 * This example takes the following command line parameters:
058 *
059 * <pre>
060 *  {@code <listenAddress> <listenPort> <ldifFile> [<keyStoreFile> <keyStorePassword> <certNickname>]}
061 * </pre>
062 */
063public final class Server {
064
065    /**
066     * Main method.
067     *
068     * @param args
069     *            The command line arguments: listen address, listen port, ldifFile,
070     *            and optionally: key store, key store password and certificate nick name
071     */
072    public static void main(final String[] args) {
073        if (args.length != 3 && args.length != 6) {
074            System.err.println("Usage: listenAddress listenPort ldifFile "
075                    + "[keyStoreFile keyStorePassword certNickname]");
076            System.exit(1);
077        }
078
079        // Parse command line arguments.
080        final String localAddress = args[0];
081        final int localPort = Integer.parseInt(args[1]);
082        final String ldifFileName = args[2];
083        final String keyStoreFileName = (args.length == 6) ? args[3] : null;
084        final String keyStorePassword = (args.length == 6) ? args[4] : null;
085        final String certNickname = (args.length == 6) ? args[5] : null;
086
087        // Create the memory backend.
088        final MemoryBackend backend;
089        try {
090            backend = new MemoryBackend(new LDIFEntryReader(new FileInputStream(ldifFileName)));
091        } catch (final IOException e) {
092            System.err.println(e.getMessage());
093            System.exit(ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue());
094            return; // Keep compiler quiet.
095        }
096
097        // Create a server connection adapter.
098        final ServerConnectionFactory<LDAPClientContext, Integer> connectionHandler =
099                Connections.newServerConnectionFactory(backend);
100
101        // Create listener.
102        LDAPListener listener = null;
103        try {
104            final LDAPListenerOptions options = new LDAPListenerOptions().setBacklog(4096);
105
106            if (keyStoreFileName != null) {
107                // Configure SSL/TLS and enable it when connections are
108                // accepted.
109                final SSLContext sslContext =
110                        new SSLContextBuilder().setKeyManager(
111                                KeyManagers.useSingleCertificate(certNickname, KeyManagers
112                                        .useKeyStoreFile(keyStoreFileName, keyStorePassword
113                                                .toCharArray(), null))).setTrustManager(
114                                TrustManagers.trustAll()).getSSLContext();
115
116                final ServerConnectionFactory<LDAPClientContext, Integer> sslWrapper =
117                        new ServerConnectionFactory<LDAPClientContext, Integer>() {
118
119                            @Override
120                            public ServerConnection<Integer> handleAccept(final LDAPClientContext clientContext)
121                                    throws LdapException {
122                                clientContext.enableTLS(sslContext, null, null, false, false);
123                                return connectionHandler.handleAccept(clientContext);
124                            }
125                        };
126
127                listener = new LDAPListener(localAddress, localPort, sslWrapper, options);
128            } else {
129                // No SSL.
130                listener = new LDAPListener(localAddress, localPort, connectionHandler, options);
131            }
132            System.out.println("Press any key to stop the server...");
133            System.in.read();
134        } catch (final Exception e) {
135            System.out.println("Error listening on " + localAddress + ":" + localPort);
136            e.printStackTrace();
137        } finally {
138            if (listener != null) {
139                listener.close();
140            }
141        }
142    }
143
144    private Server() {
145        // Not used.
146    }
147}