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 2007-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2014 ForgeRock AS
026 */
027package org.forgerock.opendj.config.dsconfig;
028
029import static com.forgerock.opendj.dsconfig.DsconfigMessages.*;
030import static com.forgerock.opendj.cli.CliMessages.*;
031import static org.forgerock.util.Utils.closeSilently;
032
033import javax.net.ssl.SSLException;
034
035import org.forgerock.opendj.config.LDAPProfile;
036import org.forgerock.opendj.config.client.ManagementContext;
037import org.forgerock.opendj.config.client.ldap.LDAPManagementContext;
038import org.forgerock.opendj.config.server.ConfigException;
039import org.forgerock.opendj.ldap.Connection;
040import org.forgerock.opendj.ldap.ConnectionFactory;
041import org.forgerock.opendj.ldap.LdapException;
042
043import com.forgerock.opendj.cli.ArgumentException;
044import com.forgerock.opendj.cli.ClientException;
045import com.forgerock.opendj.cli.CommandBuilder;
046import com.forgerock.opendj.cli.ConnectionFactoryProvider;
047import com.forgerock.opendj.cli.ConsoleApplication;
048import com.forgerock.opendj.cli.ReturnCode;
049
050/**
051 * An LDAP management context factory for the DSConfig tool.
052 */
053public final class LDAPManagementContextFactory {
054
055    /** The management context. */
056    private ManagementContext context;
057
058    /** The connection parameters command builder. */
059    private CommandBuilder contextCommandBuilder;
060
061    /** The connection factory provider. */
062    private final ConnectionFactoryProvider provider;
063
064    /** The connection factory. */
065    private final ConnectionFactory factory;
066
067    /**
068     * Creates a new LDAP management context factory based on an authenticated connection factory.
069     *
070     * @param cfp
071     *            The connection factory provider which should be used in this context.
072     * @throws ArgumentException
073     *             If an exception occurs when creating the authenticated connection factory linked to this context.
074     */
075    public LDAPManagementContextFactory(ConnectionFactoryProvider cfp) throws ArgumentException {
076        this.provider = cfp;
077        factory = cfp.getAuthenticatedConnectionFactory();
078    }
079
080    /**
081     * Closes this management context.
082     */
083    public void close() {
084        closeSilently(context);
085    }
086
087    /**
088     * Returns the command builder that provides the equivalent arguments in interactive mode to get the management
089     * context.
090     *
091     * @return the command builder that provides the equivalent arguments in interactive mode to get the management
092     *         context.
093     */
094    public CommandBuilder getContextCommandBuilder() {
095        return contextCommandBuilder;
096    }
097
098    /**
099     * Gets the management context which sub-commands should use in order to manage the directory server.
100     *
101     * @param app
102     *            The console application instance.
103     * @return Returns the management context which sub-commands should use in order to manage the directory server.
104     * @throws ArgumentException
105     *             If a management context related argument could not be parsed successfully.
106     * @throws ClientException
107     *             If the management context could not be created.
108     */
109    public ManagementContext getManagementContext(ConsoleApplication app) throws ArgumentException, ClientException {
110        // Lazily create the LDAP management context.
111        if (context == null) {
112            Connection connection;
113            final String hostName = provider.getHostname();
114            final int port = provider.getPort();
115            try {
116                connection = factory.getConnection();
117                BuildVersion.checkVersionMismatch(connection);
118            } catch (LdapException e) {
119                if (e.getCause() instanceof SSLException) {
120                    throw new ClientException(ReturnCode.CLIENT_SIDE_CONNECT_ERROR,
121                            ERR_FAILED_TO_CONNECT_NOT_TRUSTED.get(hostName, String.valueOf(port)));
122                } else {
123                    throw new ClientException(ReturnCode.CLIENT_SIDE_CONNECT_ERROR,
124                            ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(hostName, String.valueOf(port)));
125                }
126            } catch (ConfigException e) {
127                throw new ClientException(ReturnCode.ERROR_USER_DATA, e.getMessageObject());
128            } catch (Exception ex) {
129                throw new ClientException(ReturnCode.CLIENT_SIDE_CONNECT_ERROR,
130                        ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(hostName, port));
131            } finally {
132                closeSilently(factory);
133            }
134
135            context = LDAPManagementContext.newManagementContext(connection, LDAPProfile.getInstance());
136        }
137        return context;
138    }
139}