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