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 2015 ForgeRock AS
025 */
026package org.opends.server.tools;
027
028import java.io.File;
029import java.util.ArrayList;
030import java.util.Collection;
031import java.util.LinkedList;
032import java.util.List;
033
034import org.forgerock.opendj.config.LDAPProfile;
035import org.forgerock.opendj.config.ManagedObjectDefinition;
036import org.forgerock.opendj.config.client.ManagementContext;
037import org.forgerock.opendj.config.client.ldap.LDAPManagementContext;
038import org.forgerock.opendj.ldap.DN;
039import org.forgerock.opendj.server.config.client.BackendCfgClient;
040import org.forgerock.opendj.server.config.client.BackendIndexCfgClient;
041import org.forgerock.opendj.server.config.client.LocalDBBackendCfgClient;
042import org.forgerock.opendj.server.config.client.LocalDBIndexCfgClient;
043import org.forgerock.opendj.server.config.client.PluggableBackendCfgClient;
044import org.forgerock.opendj.server.config.client.RootCfgClient;
045import org.forgerock.opendj.server.config.meta.BackendCfgDefn.WritabilityMode;
046import org.forgerock.opendj.server.config.meta.BackendIndexCfgDefn;
047import org.forgerock.opendj.server.config.meta.BackendIndexCfgDefn.IndexType;
048import org.forgerock.opendj.server.config.meta.LocalDBBackendCfgDefn;
049import org.forgerock.opendj.server.config.meta.LocalDBIndexCfgDefn;
050import org.forgerock.opendj.server.config.server.BackendCfg;
051import org.opends.guitools.controlpanel.util.Utilities;
052import org.opends.quicksetup.Installation;
053import org.opends.server.backends.jeb.RemoveOnceLocalDBBackendIsPluggable;
054
055/**
056 * Utility class which can be used by tools to create a new backend with default indexes.
057 */
058public class BackendCreationHelper
059{
060  /** Describes an attribute index which should be created during installation. */
061  public static final class DefaultIndex
062  {
063    static DefaultIndex withEqualityAndSubstring(final String name)
064    {
065      return new DefaultIndex(name, true);
066    }
067
068    static DefaultIndex withEquality(final String name)
069    {
070      return new DefaultIndex(name, false);
071    }
072
073    private final String name;
074    private final boolean shouldCreateSubstringIndex;
075
076    private DefaultIndex(final String name, final boolean substringIndex)
077    {
078      this.name = name;
079      this.shouldCreateSubstringIndex = substringIndex;
080    }
081
082    /**
083     * Return the name of this default index.
084     *
085     * @return The name of this default index
086     */
087    public String getName()
088    {
089      return name;
090    }
091
092    /**
093     * Return {@code true} if the substring index type should be enabled for
094     * this index.
095     *
096     * @return {@code true} if the substring index type should be enabled for
097     *         this index.
098     */
099    public boolean shouldCreateSubstringIndex()
100    {
101      return shouldCreateSubstringIndex;
102    }
103  }
104
105  /** Default indexes to add in a new backend. */
106  public static final DefaultIndex[] DEFAULT_INDEXES = {
107    DefaultIndex.withEqualityAndSubstring("cn"),
108    DefaultIndex.withEqualityAndSubstring("givenName"),
109    DefaultIndex.withEqualityAndSubstring("mail"),
110    DefaultIndex.withEqualityAndSubstring("sn"),
111    DefaultIndex.withEqualityAndSubstring("telephoneNumber"),
112    DefaultIndex.withEquality("member"),
113    DefaultIndex.withEquality("uid"),
114    DefaultIndex.withEquality("uniqueMember")
115  };
116
117  /**
118   * Add a new backend with the provided name in the config.ldif file.
119   *
120   * @param backendName
121   *          The new backend name
122   * @param baseDNs
123   *          The base dns to add in the new backend.
124   * @param backendType
125   *          The backend type
126   * @throws Exception
127   *           If any problems occurred
128   */
129  public static void createBackendOffline(String backendName, Collection<DN> baseDNs,
130      ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendType) throws Exception
131  {
132    Utilities.initializeConfigurationFramework();
133    final File configFile = Installation.getLocal().getCurrentConfigurationFile();
134    final LDAPProfile ldapProfile = LDAPProfile.getInstance();
135    try (ManagementContext context = LDAPManagementContext.newLDIFManagementContext(configFile, ldapProfile))
136    {
137      createBackend(context.getRootConfiguration(), backendName, baseDNs, backendType);
138    }
139  }
140
141  /**
142   * Create a backend with the provided name using the provided
143   * {@code RootCfgClient}.
144   *
145   * @param rootConfiguration
146   *          The root configuration to use to create the new backend
147   * @param backendName
148   *          The new backend name
149   * @param baseDNs
150   *          The base dns to add in the new backend.
151   * @param backendType
152   *          The backend type
153   * @throws Exception
154   *           If any problems occurred
155   */
156  public static void createBackend(RootCfgClient rootConfiguration, String backendName, Collection<DN> baseDNs,
157      ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg> backendType) throws Exception
158  {
159      final BackendCfgClient backendCfgClient = rootConfiguration.createBackend(backendType, backendName, null);
160      backendCfgClient.setEnabled(true);
161      backendCfgClient.setBaseDN(baseDNs);
162      backendCfgClient.setWritabilityMode(WritabilityMode.ENABLED);
163      backendCfgClient.commit();
164
165      if (backendType instanceof LocalDBBackendCfgDefn)
166      {
167        addJEDefaultIndexes((LocalDBBackendCfgClient) backendCfgClient);
168      }
169      else
170      {
171        addBackendDefaultIndexes((PluggableBackendCfgClient) backendCfgClient);
172      }
173  }
174
175  private static void addBackendDefaultIndexes(PluggableBackendCfgClient backendCfgClient) throws Exception
176  {
177    for (DefaultIndex defaultIndex : DEFAULT_INDEXES)
178    {
179      final BackendIndexCfgClient index =
180          backendCfgClient.createBackendIndex(BackendIndexCfgDefn.getInstance(), defaultIndex.name, null);
181
182      final List<IndexType> indexTypes = new LinkedList<>();
183      indexTypes.add(IndexType.EQUALITY);
184      if (defaultIndex.shouldCreateSubstringIndex)
185      {
186        indexTypes.add(IndexType.SUBSTRING);
187      }
188      index.setIndexType(indexTypes);
189
190      index.commit();
191    }
192  }
193
194  @RemoveOnceLocalDBBackendIsPluggable
195  private static void addJEDefaultIndexes(final LocalDBBackendCfgClient jeBackendCfgClient) throws Exception
196  {
197    for (DefaultIndex defaultIndex : DEFAULT_INDEXES)
198    {
199      final LocalDBIndexCfgClient jeIndex =
200          jeBackendCfgClient.createLocalDBIndex(LocalDBIndexCfgDefn.getInstance(), defaultIndex.name, null);
201
202      final List<LocalDBIndexCfgDefn.IndexType> indexTypes = new ArrayList<>();
203      indexTypes.add(LocalDBIndexCfgDefn.IndexType.EQUALITY);
204      if (defaultIndex.shouldCreateSubstringIndex)
205      {
206        indexTypes.add(LocalDBIndexCfgDefn.IndexType.SUBSTRING);
207      }
208      jeIndex.setIndexType(indexTypes);
209
210      jeIndex.commit();
211    }
212  }
213
214}