001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2007-2010 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2016 ForgeRock AS.
016 */
017package org.forgerock.opendj.config.dsconfig;
018
019import static com.forgerock.opendj.dsconfig.DsconfigMessages.*;
020import static org.forgerock.util.Utils.closeSilently;
021
022import javax.net.ssl.SSLException;
023
024import org.forgerock.i18n.LocalizableMessage;
025import org.forgerock.opendj.config.LDAPProfile;
026import org.forgerock.opendj.config.client.ManagementContext;
027import org.forgerock.opendj.config.client.ldap.LDAPManagementContext;
028import org.forgerock.opendj.config.server.ConfigException;
029import org.forgerock.opendj.ldap.Connection;
030import org.forgerock.opendj.ldap.ConnectionFactory;
031import org.forgerock.opendj.ldap.LdapException;
032
033import com.forgerock.opendj.cli.ArgumentException;
034import com.forgerock.opendj.cli.ClientException;
035import com.forgerock.opendj.cli.CommandBuilder;
036import com.forgerock.opendj.cli.ConnectionFactoryProvider;
037import com.forgerock.opendj.cli.ReturnCode;
038
039/** An LDAP management context factory for the DSConfig tool. */
040public final class LDAPManagementContextFactory {
041
042    /** The management context. */
043    private ManagementContext context;
044
045    /** The connection parameters command builder. */
046    private final CommandBuilder contextCommandBuilder;
047    /** The connection factory provider. */
048    private final ConnectionFactoryProvider provider;
049    /** The connection factory. */
050    private final ConnectionFactory factory;
051
052    /**
053     * Creates a new LDAP management context factory based on an authenticated connection factory.
054     *
055     * @param cfp
056     *            The connection factory provider which should be used in this context.
057     * @throws ArgumentException
058     *             If an exception occurs when creating the authenticated connection factory linked to this context.
059     */
060    public LDAPManagementContextFactory(ConnectionFactoryProvider cfp) throws ArgumentException {
061        this.provider = cfp;
062        factory = cfp.getAuthenticatedConnectionFactory();
063        contextCommandBuilder = null;
064    }
065
066    /** Closes this management context. */
067    public void close() {
068        closeSilently(context);
069    }
070
071    /**
072     * Returns the command builder that provides the equivalent arguments in interactive mode to get the management
073     * context.
074     *
075     * @return the command builder that provides the equivalent arguments in interactive mode to get the management
076     *         context.
077     */
078    public CommandBuilder getContextCommandBuilder() {
079        return contextCommandBuilder;
080    }
081
082    /**
083     * Gets the management context which sub-commands should use in order to manage the directory server.
084     *
085     * @return Returns the management context which sub-commands should use in order to manage the directory server.
086     * @throws ArgumentException
087     *             If a management context related argument could not be parsed successfully.
088     * @throws ClientException
089     *             If the management context could not be created.
090     */
091    public ManagementContext getManagementContext() throws ArgumentException, ClientException {
092        // Lazily create the LDAP management context.
093        if (context == null) {
094            Connection connection;
095            final String hostName = provider.getHostname();
096            final int port = provider.getPort();
097            try {
098                connection = factory.getConnection();
099                BuildVersion.checkVersionMismatch(connection);
100            } catch (LdapException e) {
101                LocalizableMessage msg = e.getCause() instanceof SSLException
102                    ? ERR_FAILED_TO_CONNECT_NOT_TRUSTED.get(hostName, port)
103                    : ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(hostName, port);
104                throw new ClientException(ReturnCode.CLIENT_SIDE_CONNECT_ERROR, msg);
105            } catch (ConfigException e) {
106                throw new ClientException(ReturnCode.ERROR_USER_DATA, e.getMessageObject());
107            } catch (Exception ex) {
108                throw new ClientException(ReturnCode.CLIENT_SIDE_CONNECT_ERROR,
109                        ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(hostName, port));
110            } finally {
111                closeSilently(factory);
112            }
113
114            context = LDAPManagementContext.newManagementContext(connection, LDAPProfile.getInstance());
115        }
116        return context;
117    }
118}