From d161a11bcc21f7a035f069a99477df23198adfd1 Mon Sep 17 00:00:00 2001
From: Fabio Pistolesi <fabio.pistolesi@forgerock.com>
Date: Fri, 13 Feb 2015 16:24:23 +0000
Subject: [PATCH] OPENDJ-1793 Convert PersistItBackendCfg references to PluggableBackendCfg

---
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java   |   73 ++--
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java      |   18 +
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java       |   43 ++
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java    |  447 +++++++-------------------
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java |  261 ++++++++++++++
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/BackendImpl.java            |   41 +
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java      |   85 ++--
 opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java         |    2 
 8 files changed, 540 insertions(+), 430 deletions(-)

diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/BackendImpl.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/BackendImpl.java
index 8ecd8aa..594917d 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/BackendImpl.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/BackendImpl.java
@@ -27,7 +27,6 @@
 package org.opends.server.backends.jeb;
 
 import static com.sleepycat.je.EnvironmentConfig.*;
-
 import static org.opends.messages.BackendMessages.*;
 import static org.opends.messages.JebMessages.*;
 import static org.opends.server.backends.jeb.ConfigurableEnvironment.*;
@@ -206,14 +205,11 @@
     DirectoryServer.registerMonitorProvider(rootContainerMonitor);
 
     // Register as disk space monitor handler
-    File parentDirectory = getFileForPath(cfg.getDBDirectory());
-    File backendDirectory =
-        new File(parentDirectory, cfg.getBackendId());
-    diskMonitor = new DiskSpaceMonitor(getBackendID() + " backend",
-        backendDirectory, cfg.getDiskLowThreshold(), cfg.getDiskFullThreshold(),
-        5, TimeUnit.SECONDS, this);
-    diskMonitor.initializeMonitorProvider(null);
-    DirectoryServer.registerMonitorProvider(diskMonitor);
+    diskMonitor = newDiskMonitor(cfg);
+    if (diskMonitor != null)
+    {
+      DirectoryServer.registerMonitorProvider(diskMonitor);
+    }
 
     //Register as an AlertGenerator.
     DirectoryServer.registerAlertGenerator(this);
@@ -221,6 +217,18 @@
     cfg.addLocalDBChangeListener(this);
   }
 
+  private DiskSpaceMonitor newDiskMonitor(LocalDBBackendCfg cfg) throws ConfigException, InitializationException
+  {
+    File parentDirectory = getFileForPath(cfg.getDBDirectory());
+    File backendDirectory =
+        new File(parentDirectory, cfg.getBackendId());
+    DiskSpaceMonitor dm = new DiskSpaceMonitor(getBackendID() + " backend",
+        backendDirectory, cfg.getDiskLowThreshold(), cfg.getDiskFullThreshold(),
+        5, TimeUnit.SECONDS, this);
+    dm.initializeMonitorProvider(null);
+    return dm;
+  }
+
   /** {@inheritDoc} */
   @Override
   public void finalizeBackend()
@@ -1000,11 +1008,9 @@
         baseDNs = newBaseDNsArray;
       }
 
-      if(cfg.getDiskFullThreshold() != newCfg.getDiskFullThreshold() ||
-          cfg.getDiskLowThreshold() != newCfg.getDiskLowThreshold())
+      if (diskMonitor != null)
       {
-        diskMonitor.setFullThreshold(newCfg.getDiskFullThreshold());
-        diskMonitor.setLowThreshold(newCfg.getDiskLowThreshold());
+        updateDiskMonitor(diskMonitor, newCfg);
       }
 
       // Put the new configuration in place.
@@ -1018,6 +1024,15 @@
     return ccr;
   }
 
+  /**
+   * @param newCfg
+   */
+  private void updateDiskMonitor(DiskSpaceMonitor dm, LocalDBBackendCfg newCfg)
+  {
+    dm.setFullThreshold(newCfg.getDiskFullThreshold());
+    dm.setLowThreshold(newCfg.getDiskLowThreshold());
+  }
+
   private void removeDeletedBaseDNs(SortedSet<DN> newBaseDNs) throws DirectoryException
   {
     for (DN baseDN : cfg.getBaseDN())
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java
index 7ab9291..77a78d0 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java
@@ -27,17 +27,23 @@
 
 import static com.persistit.Transaction.CommitPolicy.*;
 import static java.util.Arrays.*;
+import static org.opends.messages.ConfigMessages.ERR_CONFIG_BACKEND_INSANE_MODE;
+import static org.opends.messages.ConfigMessages.ERR_CONFIG_BACKEND_MODE_INVALID;
 import static org.opends.messages.JebMessages.*;
 import static org.opends.server.util.StaticUtils.*;
 
 import java.io.File;
 import java.io.FilenameFilter;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
+import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.PersistitBackendCfg;
 import org.opends.server.admin.std.server.PluggableBackendCfg;
 import org.opends.server.backends.pluggable.spi.Cursor;
@@ -49,6 +55,9 @@
 import org.opends.server.backends.pluggable.spi.UpdateFunction;
 import org.opends.server.backends.pluggable.spi.WriteOperation;
 import org.opends.server.backends.pluggable.spi.WriteableStorage;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.FilePermission;
 
 import com.persistit.Configuration;
 import com.persistit.Configuration.BufferPoolConfiguration;
@@ -65,7 +74,7 @@
 import com.persistit.exception.RollbackException;
 
 /** PersistIt database implementation of the {@link Storage} engine. */
-public final class PersistItStorage implements Storage
+public final class PersistItStorage implements Storage, ConfigurationChangeListener<PersistitBackendCfg>
 {
   private static final String VOLUME_NAME = "dj";
   /** The buffer / page size used by the PersistIt storage. */
@@ -504,6 +513,7 @@
         throw new IllegalStateException(e);
       }
     }
+    config.removePersistitChangeListener(this);
   }
 
   /** {@inheritDoc} */
@@ -537,6 +547,7 @@
       bufferPoolCfg.setFraction(cfg.getDBCachePercent() / 100.0f);
     }
     dbCfg.setCommitPolicy(cfg.isDBTxnNoSync() ? SOFT : GROUP);
+    cfg.addPersistitChangeListener(this);
   }
 
   private BufferPoolConfiguration getBufferPoolCfg()
@@ -553,8 +564,9 @@
 
   /** {@inheritDoc} */
   @Override
-  public void open()
+  public void open() throws Exception
   {
+    setupStorageFiles();
     try
     {
       db = new Persistit(dbCfg);
@@ -621,21 +633,15 @@
 
   /** {@inheritDoc} */
   @Override
-  public Importer startImport()
+  public Importer startImport() throws Exception
   {
     clearAndCreateDbDir(backendDirectory);
     open();
     return new ImporterImpl();
   }
 
-  /**
-   * Replace persistit reserved comma character with an underscore character.
-   *
-   * @param suffix
-   *          the suffix name to convert
-   * @return a new String suitable for use as a suffix name
-   */
-  public String toSuffixName(final String suffix)
+  /** {@inheritDoc} */
+  public String toSafeSuffixName(final String suffix)
   {
     return suffix.replaceAll("[,=]", "_");
   }
@@ -700,7 +706,7 @@
     };
   }
 
-  /*
+  /**
    * TODO: it would be nice to use the low-level key/value APIs. They seem quite
    * inefficient at the moment for simple byte arrays.
    */
@@ -735,4 +741,235 @@
     }
     return null;
   }
+
+  /** {@inheritDoc} */
+  @Override
+  public boolean isConfigurationChangeAcceptable(PersistitBackendCfg cfg, List<LocalizableMessage> unacceptableReasons)
+  {
+    boolean acceptable = true;
+
+    File parentDirectory = getFileForPath(config.getDBDirectory());
+    File backendDirectory = new File(parentDirectory, config.getBackendId());
+
+    //Make sure the directory either already exists or is able to create.
+    if (!backendDirectory.exists())
+    {
+      if(!backendDirectory.mkdirs())
+      {
+        unacceptableReasons.add(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath()));
+        acceptable = false;
+      }
+      else
+      {
+        backendDirectory.delete();
+      }
+    }
+    else if (!backendDirectory.isDirectory())
+    {
+      unacceptableReasons.add(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()));
+      acceptable = false;
+    }
+
+    try
+    {
+      FilePermission newBackendPermission =
+          FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions());
+
+      //Make sure the mode will allow the server itself access to the database
+      if(!newBackendPermission.isOwnerWritable() ||
+          !newBackendPermission.isOwnerReadable() ||
+          !newBackendPermission.isOwnerExecutable())
+      {
+        LocalizableMessage message = ERR_CONFIG_BACKEND_INSANE_MODE.get(
+            cfg.getDBDirectoryPermissions());
+        unacceptableReasons.add(message);
+        acceptable = false;
+      }
+    }
+    catch(Exception e)
+    {
+      unacceptableReasons.add(ERR_CONFIG_BACKEND_MODE_INVALID.get(cfg.dn()));
+      acceptable = false;
+    }
+
+    return acceptable;
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public ConfigChangeResult applyConfigurationChange(PersistitBackendCfg cfg)
+  {
+    final ConfigChangeResult ccr = new ConfigChangeResult();
+
+    try
+    {
+      // Create the directory if it doesn't exist.
+      if(!cfg.getDBDirectory().equals(this.config.getDBDirectory()))
+      {
+        File parentDirectory = getFileForPath(cfg.getDBDirectory());
+        File backendDirectory =
+          new File(parentDirectory, cfg.getBackendId());
+
+        if (!backendDirectory.exists())
+        {
+          if (!backendDirectory.mkdirs())
+          {
+            ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+            ccr.addMessage(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath()));
+            return ccr;
+          }
+        }
+        //Make sure the directory is valid.
+        else if (!backendDirectory.isDirectory())
+        {
+          ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+          ccr.addMessage(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()));
+          return ccr;
+        }
+
+        ccr.setAdminActionRequired(true);
+        ccr.addMessage(NOTE_JEB_CONFIG_DB_DIR_REQUIRES_RESTART.get(this.config.getDBDirectory(),
+            cfg.getDBDirectory()));
+      }
+
+      if (!cfg.getDBDirectoryPermissions().equalsIgnoreCase(config.getDBDirectoryPermissions())
+          || !cfg.getDBDirectory().equals(this.config.getDBDirectory()))
+      {
+        FilePermission backendPermission;
+        try
+        {
+          backendPermission =
+              FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions());
+        }
+        catch(Exception e)
+        {
+          ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+          ccr.addMessage(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn()));
+          return ccr;
+        }
+
+        // Make sure the mode will allow the server itself access to the database
+        if(!backendPermission.isOwnerWritable() ||
+            !backendPermission.isOwnerReadable() ||
+            !backendPermission.isOwnerExecutable())
+        {
+          ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+          ccr.addMessage(ERR_CONFIG_BACKEND_INSANE_MODE.get(cfg.getDBDirectoryPermissions()));
+          return ccr;
+        }
+
+        // Get the backend database backendDirectory permissions and apply
+        if(FilePermission.canSetPermissions())
+        {
+          File parentDirectory = getFileForPath(config.getDBDirectory());
+          File backendDirectory = new File(parentDirectory, config.getBackendId());
+          try
+          {
+            if (!FilePermission.setPermissions(backendDirectory, backendPermission))
+            {
+              logger.warn(WARN_JEB_UNABLE_SET_PERMISSIONS, backendPermission, backendDirectory);
+            }
+          }
+          catch(Exception e)
+          {
+            // Log an warning that the permissions were not set.
+            logger.warn(WARN_JEB_SET_PERMISSIONS_FAILED, backendDirectory, e);
+          }
+        }
+      }
+
+      this.config = cfg;
+    }
+    catch (Exception e)
+    {
+      ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+      ccr.addMessage(LocalizableMessage.raw(stackTraceToSingleLineString(e)));
+    }
+    return ccr;
+  }
+
+  /** {@inheritDoc} */
+  private void setupStorageFiles() throws Exception
+  {
+    // Create the directory if it doesn't exist.
+    if (!backendDirectory.exists())
+    {
+      if(!backendDirectory.mkdirs())
+      {
+        LocalizableMessage message =
+          ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath());
+        throw new ConfigException(message);
+      }
+    }
+    //Make sure the directory is valid.
+    else if (!backendDirectory.isDirectory())
+    {
+      throw new ConfigException(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()));
+    }
+
+    FilePermission backendPermission;
+    try
+    {
+      backendPermission =
+          FilePermission.decodeUNIXMode(config.getDBDirectoryPermissions());
+    }
+    catch(Exception e)
+    {
+      throw new ConfigException(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn()));
+    }
+
+    //Make sure the mode will allow the server itself access to
+    //the database
+    if(!backendPermission.isOwnerWritable() ||
+        !backendPermission.isOwnerReadable() ||
+        !backendPermission.isOwnerExecutable())
+    {
+      LocalizableMessage message = ERR_CONFIG_BACKEND_INSANE_MODE.get(
+          config.getDBDirectoryPermissions());
+      throw new ConfigException(message);
+    }
+
+    // Get the backend database backendDirectory permissions and apply
+    if(FilePermission.canSetPermissions())
+    {
+      try
+      {
+        if(!FilePermission.setPermissions(backendDirectory, backendPermission))
+        {
+          logger.warn(WARN_JEB_UNABLE_SET_PERMISSIONS, backendPermission, backendDirectory);
+        }
+      }
+      catch(Exception e)
+      {
+        // Log an warning that the permissions were not set.
+        logger.warn(WARN_JEB_SET_PERMISSIONS_FAILED, backendDirectory, e);
+      }
+    }
+  }
+
+  /** {@inheritDoc} */
+  public void removeStorageFiles() throws StorageRuntimeException
+  {
+    if (!backendDirectory.isDirectory())
+    {
+      LocalizableMessage msg = ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath());
+      throw new StorageRuntimeException(msg.toString());
+    }
+
+    try
+    {
+      File[] files = backendDirectory.listFiles();
+      for (File f : files)
+      {
+        f.delete();
+      }
+    }
+    catch (Exception e)
+    {
+      logger.traceException(e);
+      LocalizableMessage message = ERR_JEB_REMOVE_FAIL.get(e.getMessage());
+      throw new StorageRuntimeException(message.toString(), e);
+    }
+  }
 }
+
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java
index b83572f..9c84a9c 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java
@@ -26,19 +26,60 @@
 
 package org.opends.server.backends.persistit;
 
+import static org.opends.server.util.StaticUtils.getFileForPath;
+
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+
+import org.forgerock.opendj.config.server.ConfigException;
+import org.opends.server.admin.std.server.PersistitBackendCfg;
+import org.opends.server.admin.std.server.PluggableBackendCfg;
 import org.opends.server.backends.pluggable.BackendImpl;
 import org.opends.server.backends.pluggable.spi.Storage;
+import org.opends.server.extensions.DiskSpaceMonitor;
+import org.opends.server.types.InitializationException;
 
 /**
  * Class defined in the configuration for this backend type.
  */
 public class PitBackend extends BackendImpl
 {
-
   /** {@inheritDoc} */
   @Override
   protected Storage newStorageInstance()
   {
     return new PersistItStorage();
   }
+
+  /** {@inheritDoc} */
+  @Override
+  public DiskSpaceMonitor newDiskMonitor(PluggableBackendCfg cfg) throws ConfigException, InitializationException
+  {
+    PersistitBackendCfg config = (PersistitBackendCfg) cfg;
+    File parentDirectory = getFileForPath(config.getDBDirectory());
+    File backendDirectory =
+        new File(parentDirectory, config.getBackendId());
+    DiskSpaceMonitor dm = new DiskSpaceMonitor(getBackendID() + " backend",
+        backendDirectory, config.getDiskLowThreshold(), config.getDiskFullThreshold(),
+        5, TimeUnit.SECONDS, this);
+    dm.initializeMonitorProvider(null);
+    return dm;
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void updateDiskMonitor(DiskSpaceMonitor dm, PluggableBackendCfg newConfig)
+  {
+    PersistitBackendCfg newCfg = (PersistitBackendCfg) newConfig;
+    dm.setFullThreshold(newCfg.getDiskFullThreshold());
+    dm.setLowThreshold(newCfg.getDiskLowThreshold());
+  }
+
+  /** {@inheritDoc} */
+  protected File getBackupDirectory(PluggableBackendCfg cfg)
+  {
+    PersistitBackendCfg config = (PersistitBackendCfg) cfg;
+    File parentDir = getFileForPath(config.getDBDirectory());
+    return new File(parentDir, config.getBackendId());
+  }
 }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java
index 1040b87..77c929a 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java
@@ -35,7 +35,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.*;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.forgerock.i18n.LocalizableMessage;
@@ -47,7 +46,7 @@
 import org.forgerock.util.Reject;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.meta.BackendIndexCfgDefn;
-import org.opends.server.admin.std.server.PersistitBackendCfg;
+import org.opends.server.admin.std.server.PluggableBackendCfg;
 import org.opends.server.api.AlertGenerator;
 import org.opends.server.api.Backend;
 import org.opends.server.api.DiskSpaceMonitorHandler;
@@ -65,14 +64,14 @@
  * This is an implementation of a Directory Server Backend which stores entries
  * locally in a Berkeley DB JE database.
  */
-public abstract class BackendImpl extends Backend<PersistitBackendCfg> implements
-    ConfigurationChangeListener<PersistitBackendCfg>, AlertGenerator,
+public abstract class BackendImpl extends Backend<PluggableBackendCfg> implements
+    ConfigurationChangeListener<PluggableBackendCfg>, AlertGenerator,
     DiskSpaceMonitorHandler
 {
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
   /** The configuration of this backend. */
-  private PersistitBackendCfg cfg;
+  private PluggableBackendCfg cfg;
   /** The root JE container to use for this backend. */
   private RootContainer rootContainer;
 
@@ -83,6 +82,7 @@
   private DN[] baseDNs;
 
   private MonitorProvider<?> rootContainerMonitor;
+  /** Disk space monitoring if the storage supports it. */
   private DiskSpaceMonitor diskMonitor;
 
   /** The controls supported by this backend. */
@@ -128,7 +128,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public void configureBackend(PersistitBackendCfg cfg) throws ConfigException
+  public void configureBackend(PluggableBackendCfg cfg) throws ConfigException
   {
     Reject.ifNull(cfg);
 
@@ -179,27 +179,44 @@
     DirectoryServer.registerMonitorProvider(rootContainerMonitor);
 
     // Register as disk space monitor handler
-    File parentDirectory = getFileForPath(cfg.getDBDirectory());
-    File backendDirectory =
-        new File(parentDirectory, cfg.getBackendId());
-    diskMonitor = new DiskSpaceMonitor(getBackendID() + " backend",
-        backendDirectory, cfg.getDiskLowThreshold(), cfg.getDiskFullThreshold(),
-        5, TimeUnit.SECONDS, this);
-    diskMonitor.initializeMonitorProvider(null);
-    DirectoryServer.registerMonitorProvider(diskMonitor);
-
+    diskMonitor = newDiskMonitor(cfg);
+    if (diskMonitor != null)
+    {
+      DirectoryServer.registerMonitorProvider(diskMonitor);
+    }
     //Register as an AlertGenerator.
     DirectoryServer.registerAlertGenerator(this);
     // Register this backend as a change listener.
-    cfg.addPersistitChangeListener(this);
+    cfg.addPluggableChangeListener(this);
   }
 
+  /**
+   * Let the storage create a new disk monitor if supported.
+   *
+   * @param cfg this storage current configuration
+   * @return a new disk monitor if supported or null
+   *
+   * @throws ConfigException if configuration is incorrect
+   * @throws InitializationException when disk monitor cannot be initialized
+   */
+  protected abstract DiskSpaceMonitor newDiskMonitor(PluggableBackendCfg cfg) throws
+    ConfigException, InitializationException;
+
+  /**
+   * Updates the disk monitor when configuration changes.
+   *
+   * @param dm the disk monitor to update
+   * @param newCfg the new configuration
+   */
+  protected abstract void updateDiskMonitor(DiskSpaceMonitor dm, PluggableBackendCfg newCfg);
+
+
   /** {@inheritDoc} */
   @Override
   public void finalizeBackend()
   {
     super.finalizeBackend();
-    cfg.removePersistitChangeListener(this);
+    cfg.removePluggableChangeListener(this);
 
     // Deregister our base DNs.
     for (DN dn : rootContainer.getBaseDNs())
@@ -722,8 +739,7 @@
   public void createBackup(BackupConfig backupConfig) throws DirectoryException
   {
     BackupManager backupManager = new BackupManager(getBackendID());
-    File parentDir = getFileForPath(cfg.getDBDirectory());
-    File backendDir = new File(parentDir, cfg.getBackendId());
+    File backendDir = getBackupDirectory(cfg);
     Storage storage = newStorageInstance();
     backupConfig.setFilesToBackupFilter(storage.getFilesToBackupFilter());
     backupManager.createBackup(backendDir, backupConfig);
@@ -735,7 +751,6 @@
    */
   protected abstract Storage newStorageInstance();
 
-
   /** {@inheritDoc} */
   @Override
   public void removeBackup(BackupDirectory backupDirectory, String backupID)
@@ -745,25 +760,27 @@
     backupManager.removeBackup(backupDirectory, backupID);
   }
 
-
-
   /** {@inheritDoc} */
   @Override
   public void restoreBackup(RestoreConfig restoreConfig)
       throws DirectoryException
   {
     BackupManager backupManager = new BackupManager(getBackendID());
-    File parentDir = getFileForPath(cfg.getDBDirectory());
-    File backendDir = new File(parentDir, cfg.getBackendId());
+    File backendDir = getBackupDirectory(cfg);
     backupManager.restoreBackup(backendDir, restoreConfig);
   }
 
-
+  /**
+   * Returns the backup directory.
+   *
+   * @param cfg the configuration for this backend
+   * @return the backup directory
+   */
+  protected abstract File getBackupDirectory(PluggableBackendCfg cfg);
 
   /** {@inheritDoc} */
   @Override
-  public boolean isConfigurationAcceptable(PersistitBackendCfg config,
-                                           List<LocalizableMessage> unacceptableReasons)
+  public boolean isConfigurationAcceptable(PluggableBackendCfg config, List<LocalizableMessage> unacceptableReasons)
   {
     return isConfigurationChangeAcceptable(config, unacceptableReasons);
   }
@@ -772,9 +789,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public boolean isConfigurationChangeAcceptable(
-      PersistitBackendCfg cfg,
-      List<LocalizableMessage> unacceptableReasons)
+  public boolean isConfigurationChangeAcceptable(PluggableBackendCfg cfg, List<LocalizableMessage> unacceptableReasons)
   {
     return true;
   }
@@ -783,7 +798,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public ConfigChangeResult applyConfigurationChange(final PersistitBackendCfg newCfg)
+  public ConfigChangeResult applyConfigurationChange(final PluggableBackendCfg newCfg)
   {
     final ConfigChangeResult ccr = new ConfigChangeResult();
     try
@@ -807,11 +822,9 @@
 
             baseDNs = newBaseDNsArray;
 
-            if(cfg.getDiskFullThreshold() != newCfg.getDiskFullThreshold() ||
-                cfg.getDiskLowThreshold() != newCfg.getDiskLowThreshold())
+            if (diskMonitor != null)
             {
-              diskMonitor.setFullThreshold(newCfg.getDiskFullThreshold());
-              diskMonitor.setLowThreshold(newCfg.getDiskLowThreshold());
+              updateDiskMonitor(diskMonitor, newCfg);
             }
 
             // Put the new configuration in place.
@@ -906,7 +919,7 @@
    *          The StorageRuntimeException to be converted.
    * @return DirectoryException created from exception.
    */
-  DirectoryException createDirectoryException(StorageRuntimeException e)
+  private DirectoryException createDirectoryException(StorageRuntimeException e)
   {
     if (true) // FIXME JNR
     {
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
index b83a2ea..b1eb8f8 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
@@ -60,7 +60,7 @@
 import org.opends.server.admin.server.ConfigurationDeleteListener;
 import org.opends.server.admin.std.server.BackendIndexCfg;
 import org.opends.server.admin.std.server.BackendVLVIndexCfg;
-import org.opends.server.admin.std.server.PersistitBackendCfg;
+import org.opends.server.admin.std.server.PluggableBackendCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.EntryCache;
@@ -109,14 +109,14 @@
  * the guts of the backend API methods for LDAP operations.
  */
 public class EntryContainer
-    implements SuffixContainer, ConfigurationChangeListener<PersistitBackendCfg>
+    implements SuffixContainer, ConfigurationChangeListener<PluggableBackendCfg>
 {
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
   /** The name of the entry database. */
-  public static final String ID2ENTRY_DATABASE_NAME = ID2ENTRY_INDEX_NAME;
+  private static final String ID2ENTRY_DATABASE_NAME = ID2ENTRY_INDEX_NAME;
   /** The name of the DN database. */
-  public static final String DN2ID_DATABASE_NAME = DN2ID_INDEX_NAME;
+  private static final String DN2ID_DATABASE_NAME = DN2ID_INDEX_NAME;
   /** The name of the children index database. */
   private static final String ID2CHILDREN_DATABASE_NAME = ID2CHILDREN_INDEX_NAME;
   /** The name of the subtree index database. */
@@ -141,7 +141,7 @@
   private final DN baseDN;
 
   /** The backend configuration. */
-  private PersistitBackendCfg config;
+  private PluggableBackendCfg config;
 
   /** The JE database environment. */
   private final Storage storage;
@@ -441,8 +441,8 @@
    * @param rootContainer The root container this entry container is in.
    * @throws ConfigException if a configuration related error occurs.
    */
-  public EntryContainer(DN baseDN, String databasePrefix, Backend<?> backend,
-      PersistitBackendCfg config, Storage env, RootContainer rootContainer)
+  EntryContainer(DN baseDN, String databasePrefix, Backend<?> backend,
+      PluggableBackendCfg config, Storage env, RootContainer rootContainer)
           throws ConfigException
   {
     this.backend = backend;
@@ -452,7 +452,7 @@
     this.rootContainer = rootContainer;
     this.databasePrefix = databasePrefix;
 
-    config.addPersistitChangeListener(this);
+    config.addPluggableChangeListener(this);
 
     attributeJEIndexCfgManager = new AttributeJEIndexCfgManager();
     config.addBackendIndexAddListener(attributeJEIndexCfgManager);
@@ -475,7 +475,7 @@
    * @throws StorageRuntimeException If an error occurs in the JE database.
    * @throws ConfigException if a configuration related error occurs.
    */
-  public void open(WriteableStorage txn) throws StorageRuntimeException, ConfigException
+  void open(WriteableStorage txn) throws StorageRuntimeException, ConfigException
   {
     try
     {
@@ -577,7 +577,7 @@
     }
 
     // Deregister any listeners.
-    config.removePersistitChangeListener(this);
+    config.removePluggableChangeListener(this);
     config.removeBackendIndexAddListener(attributeJEIndexCfgManager);
     config.removeBackendIndexDeleteListener(attributeJEIndexCfgManager);
     config.removeBackendVLVIndexAddListener(vlvJEIndexCfgManager);
@@ -668,7 +668,7 @@
    * @param attrType The attribute type for which an attribute index is needed.
    * @return The attribute index or null if there is none for that type.
    */
-  public AttributeIndex getAttributeIndex(AttributeType attrType)
+  AttributeIndex getAttributeIndex(AttributeType attrType)
   {
     return attrIndexMap.get(attrType);
   }
@@ -688,7 +688,7 @@
    * @param vlvIndexName The vlv index name for which an vlv index is needed.
    * @return The VLV index or null if there is none with that name.
    */
-  public VLVIndex getVLVIndex(String vlvIndexName)
+  VLVIndex getVLVIndex(String vlvIndexName)
   {
     return vlvIndexMap.get(vlvIndexName);
   }
@@ -721,7 +721,7 @@
    * @return The highest entry ID.
    * @throws StorageRuntimeException If an error occurs in the JE database.
    */
-  public EntryID getHighestEntryID(ReadableStorage txn) throws StorageRuntimeException
+  EntryID getHighestEntryID(ReadableStorage txn) throws StorageRuntimeException
   {
     Cursor cursor = txn.openCursor(id2entry.getName());
     try
@@ -750,7 +750,7 @@
    *         the entry does not exist.
    * @throws StorageRuntimeException If an error occurs in the JE database.
    */
-  public long getNumSubordinates(final DN entryDN, final boolean subtree)
+  long getNumSubordinates(final DN entryDN, final boolean subtree)
   throws StorageRuntimeException
   {
     try
@@ -801,7 +801,7 @@
    * @throws StorageRuntimeException If an error occurs in the JE database.
    * @throws CanceledOperationException if this operation should be cancelled.
    */
-  public void search(final SearchOperation searchOperation)
+  void search(final SearchOperation searchOperation)
   throws DirectoryException, StorageRuntimeException, CanceledOperationException
   {
     try
@@ -819,7 +819,7 @@
               searchOperation.getRequestControl(ServerSideSortRequestControl.DECODER);
           if (sortRequest != null && !sortRequest.containsSortKeys() && sortRequest.isCritical())
           {
-            /**
+            /*
              * If the control's criticality field is true then the server SHOULD
              * do the following: return unavailableCriticalExtension as a return
              * code in the searchResultDone message; include the
@@ -1316,7 +1316,7 @@
    * @throws DirectoryException
    *           If an error occurs retrieving the entry
    */
-  public Entry getEntry(ReadableStorage txn, EntryID entryID) throws DirectoryException
+  Entry getEntry(ReadableStorage txn, EntryID entryID) throws DirectoryException
   {
     // Try the entry cache first.
     final EntryCache entryCache = getEntryCache();
@@ -1421,12 +1421,8 @@
         }
 
         // Process the candidate entry.
-        if (entry != null)
-        {
-          // Filter the entry if it is in scope.
-          if (isInScope(candidatesAreInScope, searchScope, aBaseDN, entry)
-              && (manageDsaIT || entry.getReferralURLs() == null)
-              && searchOperation.getFilter().matchesEntry(entry))
+        if (entry != null && isInScope(candidatesAreInScope, searchScope, aBaseDN, entry)
+              && (manageDsaIT || entry.getReferralURLs() == null) && searchOperation.getFilter().matchesEntry(entry))
           {
             if (pageRequest != null
                 && searchOperation.getEntriesSent() == pageRequest.getSize())
@@ -1447,7 +1443,6 @@
               break;
             }
           }
-        }
       }
       searchOperation.checkIfCanceled(false);
     }
@@ -1521,7 +1516,7 @@
    * @throws StorageRuntimeException If an error occurs in the JE database.
    * @throws CanceledOperationException if this operation should be cancelled.
    */
-  public void addEntry(final Entry entry, final AddOperation addOperation)
+  void addEntry(final Entry entry, final AddOperation addOperation)
   throws StorageRuntimeException, DirectoryException, CanceledOperationException
   {
     try
@@ -1676,7 +1671,7 @@
    * @throws StorageRuntimeException If an error occurs in the JE database.
    * @throws CanceledOperationException if this operation should be cancelled.
    */
-  public void deleteEntry(final DN entryDN, final DeleteOperation deleteOperation)
+  void deleteEntry(final DN entryDN, final DeleteOperation deleteOperation)
   throws DirectoryException, StorageRuntimeException, CanceledOperationException
   {
     try
@@ -1934,7 +1929,7 @@
    * @throws  DirectoryException  If a problem occurs while trying to make the
    *                              determination.
    */
-  public boolean entryExists(final DN entryDN) throws DirectoryException
+  private boolean entryExists(final DN entryDN) throws DirectoryException
   {
     // Try the entry cache first.
     EntryCache<?> entryCache = DirectoryServer.getEntryCache();
@@ -1975,7 +1970,7 @@
    *                            the entry.
    * @throws StorageRuntimeException An error occurred during a database operation.
    */
-  public Entry getEntry(final DN entryDN) throws StorageRuntimeException, DirectoryException
+  Entry getEntry(final DN entryDN) throws StorageRuntimeException, DirectoryException
   {
     try
     {
@@ -2060,7 +2055,7 @@
    * @throws DirectoryException If a Directory Server error occurs.
    * @throws CanceledOperationException if this operation should be cancelled.
    */
-  public void replaceEntry(final Entry oldEntry, final Entry newEntry, final ModifyOperation modifyOperation)
+  void replaceEntry(final Entry oldEntry, final Entry newEntry, final ModifyOperation modifyOperation)
       throws StorageRuntimeException, DirectoryException, CanceledOperationException
   {
     try
@@ -2187,7 +2182,7 @@
    *          modify DN operation.
    * @throws StorageRuntimeException If an error occurs in the JE database.
    */
-  public void renameEntry(final DN currentDN, final Entry entry, final ModifyDNOperation modifyDNOperation)
+  void renameEntry(final DN currentDN, final Entry entry, final ModifyDNOperation modifyDNOperation)
       throws StorageRuntimeException, DirectoryException, CanceledOperationException
   {
     try
@@ -2640,7 +2635,7 @@
    * @param newSuffixDN The new DN of the renamed or moved entry.
    * @return The new DN of the subordinate entry.
    */
-  public static DN modDN(DN oldDN, int oldSuffixLen, DN newSuffixDN)
+  static DN modDN(DN oldDN, int oldSuffixLen, DN newSuffixDN)
   {
     int oldDNNumComponents    = oldDN.size();
     int oldDNKeepComponents   = oldDNNumComponents - oldSuffixLen;
@@ -2745,7 +2740,7 @@
    * @return The number of entries stored in this entry container.
    * @throws StorageRuntimeException If an error occurs in the JE database.
    */
-  public long getEntryCount(ReadableStorage txn) throws StorageRuntimeException
+  long getEntryCount(ReadableStorage txn) throws StorageRuntimeException
   {
     final EntryID entryID = dn2id.get(txn, baseDN, false);
     if (entryID != null)
@@ -2793,7 +2788,7 @@
    * Get a list of the databases opened by the entryContainer.
    * @param dbList A list of database containers.
    */
-  public void listDatabases(List<DatabaseContainer> dbList)
+  void listDatabases(List<DatabaseContainer> dbList)
   {
     dbList.add(dn2id);
     dbList.add(id2entry);
@@ -2847,7 +2842,7 @@
    * @throws StorageRuntimeException If an error occurs while removing the entry
    *                           container.
    */
-  public void delete(WriteableStorage txn) throws StorageRuntimeException
+  void delete(WriteableStorage txn) throws StorageRuntimeException
   {
     List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
     listDatabases(databases);
@@ -2866,7 +2861,7 @@
    * @throws StorageRuntimeException If an error occurs while attempting to delete the
    * database.
    */
-  public void deleteDatabase(WriteableStorage txn, DatabaseContainer database) throws StorageRuntimeException
+  void deleteDatabase(WriteableStorage txn, DatabaseContainer database) throws StorageRuntimeException
   {
     if(database == state)
     {
@@ -3011,7 +3006,7 @@
    * @param dn A DN which is in the scope of the base DN.
    * @return The parent DN, or null if the given DN is the base DN.
    */
-  public DN getParentWithinBase(DN dn)
+  DN getParentWithinBase(DN dn)
   {
     if (dn.equals(baseDN))
     {
@@ -3023,7 +3018,7 @@
   /** {@inheritDoc} */
   @Override
   public boolean isConfigurationChangeAcceptable(
-      PersistitBackendCfg cfg, List<LocalizableMessage> unacceptableReasons)
+      PluggableBackendCfg cfg, List<LocalizableMessage> unacceptableReasons)
   {
     // This is always true because only all config attributes used
     // by the entry container should be validated by the admin framework.
@@ -3032,7 +3027,7 @@
 
   /** {@inheritDoc} */
   @Override
-  public ConfigChangeResult applyConfigurationChange(final PersistitBackendCfg cfg)
+  public ConfigChangeResult applyConfigurationChange(final PluggableBackendCfg cfg)
   {
     final ConfigChangeResult ccr = new ConfigChangeResult();
 
@@ -3345,6 +3340,6 @@
   /** {@inheritDoc} */
   @Override
   public String toString() {
-    return databasePrefix.toString();
+    return databasePrefix;
   }
 }
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java
index 6a323f0..1b40aef 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java
@@ -4054,7 +4054,7 @@
       }
       finally
       {
-        rootContainer.removeFiles();
+        storage.removeStorageFiles();
       }
     }
 
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java
index 3987037..f887025 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java
@@ -26,15 +26,24 @@
  */
 package org.opends.server.backends.pluggable;
 
-import static org.opends.messages.BackendMessages.*;
-import static org.opends.messages.ConfigMessages.*;
-import static org.opends.messages.JebMessages.*;
-import static org.opends.messages.UtilityMessages.*;
-import static org.opends.server.core.DirectoryServer.*;
-import static org.opends.server.util.StaticUtils.*;
+import static org.opends.messages.BackendMessages.ERR_LDIF_BACKEND_CANNOT_CREATE_LDIF_READER;
+import static org.opends.messages.BackendMessages.ERR_LDIF_BACKEND_ERROR_READING_LDIF;
+import static org.opends.messages.JebMessages.ERR_JEB_CACHE_PRELOAD;
+import static org.opends.messages.JebMessages.ERR_JEB_REMOVE_FAIL;
+import static org.opends.messages.JebMessages.ERR_JEB_ENTRY_CONTAINER_ALREADY_REGISTERED;
+import static org.opends.messages.JebMessages.ERR_JEB_IMPORT_PARENT_NOT_FOUND;
+import static org.opends.messages.JebMessages.NOTE_JEB_IMPORT_FINAL_STATUS;
+import static org.opends.messages.JebMessages.NOTE_JEB_IMPORT_PROGRESS_REPORT;
+import static org.opends.messages.JebMessages.WARN_JEB_IMPORT_ENTRY_EXISTS;
+import static org.opends.messages.UtilityMessages.ERR_LDIF_SKIP;
+import static org.opends.server.core.DirectoryServer.getServerErrorResultCode;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
 
-import java.io.File;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
@@ -45,9 +54,8 @@
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.server.ConfigurationChangeListener;
-import org.opends.server.admin.std.server.PersistitBackendCfg;
+import org.opends.server.admin.std.server.PluggableBackendCfg;
 import org.opends.server.api.CompressedSchema;
-import org.opends.server.backends.persistit.PersistItStorage;
 import org.opends.server.backends.pluggable.spi.ReadOperation;
 import org.opends.server.backends.pluggable.spi.ReadableStorage;
 import org.opends.server.backends.pluggable.spi.Storage;
@@ -58,7 +66,6 @@
 import org.opends.server.types.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
-import org.opends.server.types.FilePermission;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.LDIFImportResult;
@@ -67,13 +74,13 @@
 import org.opends.server.util.LDIFReader;
 import org.opends.server.util.RuntimeInformation;
 
+
 /**
  * Wrapper class for the JE environment. Root container holds all the entry
  * containers for each base DN. It also maintains all the openings and closings
  * of the entry containers.
  */
-public class RootContainer
-     implements ConfigurationChangeListener<PersistitBackendCfg>
+public class RootContainer implements ConfigurationChangeListener<PluggableBackendCfg>
 {
   /** Logs the progress of the import. */
   private static final class ImportProgress implements Runnable
@@ -112,16 +119,14 @@
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
   private static final int IMPORT_PROGRESS_INTERVAL = 10000;
-  private static final int KB = 1024;
 
   /** The JE database environment. */
-  private PersistItStorage storage; // FIXME JNR do not hardcode here
+  private Storage storage;
 
-  private final File backendDirectory;
   /** The backend to which this entry root container belongs. */
   private final BackendImpl backend;
   /** The backend configuration. */
-  private PersistitBackendCfg config;
+  private PluggableBackendCfg config;
   /** The database environment monitor for this JE environment. */
   private DatabaseEnvironmentMonitor monitor;
 
@@ -134,26 +139,25 @@
   /** The compressed schema manager for this backend. */
   private JECompressedSchema compressedSchema;
 
-
   /**
    * Creates a new RootContainer object. Each root container represents a JE
    * environment.
    *
-   * @param config The configuration of the JE backend.
-   * @param backend A reference to the JE back end that is creating this
-   *                root container.
+   * @param config
+   *          The configuration of the JE backend.
+   * @param backend
+   *          A reference to the JE back end that is creating this root
+   *          container.
    */
-  public RootContainer(BackendImpl backend, PersistitBackendCfg config)
+  RootContainer(BackendImpl backend, PluggableBackendCfg config)
   {
     this.backend = backend;
     this.config = config;
-    this.backendDirectory = new File(getFileForPath(config.getDBDirectory()),
-        config.getBackendId());
 
     getMonitorProvider().enableFilterUseStats(config.isIndexFilterAnalyzerEnabled());
     getMonitorProvider().setMaxEntries(config.getIndexFilterAnalyzerMaxFilters());
 
-    config.addPersistitChangeListener(this);
+    config.addPluggableChangeListener(this);
   }
 
   /**
@@ -167,20 +171,33 @@
   }
 
   /**
-   * Imports information from an LDIF file into this backend.
-   * This method should only be called if {@code supportsLDIFImport} returns {@code true}.
-   * Note that the server will not explicitly initialize this backend before calling this method.
+   * Imports information from an LDIF file into this backend. This method should
+   * only be called if {@code supportsLDIFImport} returns {@code true}. <p>Note
+   * that the server will not explicitly initialize this backend before calling
+   * this method.
    *
-   * @param importConfig The configuration to use when performing the import.
+   * @param importConfig
+   *          The configuration to use when performing the import.
    * @return information about the result of the import processing.
-   * @throws DirectoryException If a problem occurs while performing the LDIF import.
+   * @throws DirectoryException
+   *           If a problem occurs while performing the LDIF import.
    */
   LDIFImportResult importLDIF(LDIFImportConfig importConfig) throws DirectoryException
   {
     RuntimeInformation.logInfo();
     if (Importer.mustClearBackend(importConfig, config))
     {
-      removeFiles();
+      try
+      {
+        Storage storage = backend.newStorageInstance();
+        storage.initialize(config);
+        storage.removeStorageFiles();
+      }
+      catch (Exception e)
+      {
+        LocalizableMessage m = ERR_JEB_REMOVE_FAIL.get(e.getMessage());
+        throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), m, e);
+      }
     }
     try
     {
@@ -275,8 +292,8 @@
         {
           rate = 1000f * reader.getEntriesRead() / importTime;
         }
-        logger.info(NOTE_JEB_IMPORT_FINAL_STATUS, reader.getEntriesRead(), importCount,
-            reader.getEntriesIgnored(), reader.getEntriesRejected(), 0, importTime / 1000, rate);
+        logger.info(NOTE_JEB_IMPORT_FINAL_STATUS, reader.getEntriesRead(), importCount, reader.getEntriesIgnored(),
+            reader.getEntriesRejected(), 0, importTime / 1000, rate);
         return new LDIFImportResult(reader.getEntriesRead(), reader.getEntriesRejected(), reader.getEntriesIgnored());
       }
       finally
@@ -311,35 +328,6 @@
   }
 
   /**
-   * Removes all the files from the rootContainer's directory.
-   *
-   * @throws StorageRuntimeException If a problem occurred
-   */
-  void removeFiles() throws StorageRuntimeException
-  {
-    if (!backendDirectory.isDirectory())
-    {
-      LocalizableMessage msg = ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath());
-      throw new StorageRuntimeException(msg.toString());
-    }
-
-    try
-    {
-      File[] jdbFiles = backendDirectory.listFiles();
-      for (File f : jdbFiles)
-      {
-        f.delete();
-      }
-    }
-    catch (Exception e)
-    {
-      logger.traceException(e);
-      LocalizableMessage message = ERR_JEB_REMOVE_FAIL.get(e.getMessage());
-      throw new StorageRuntimeException(message.toString(), e);
-    }
-  }
-
-  /**
    * Opens the root container.
    *
    * @throws StorageRuntimeException
@@ -349,64 +337,9 @@
    */
   void open() throws StorageRuntimeException, ConfigException
   {
-    // Create the directory if it doesn't exist.
-    if (!backendDirectory.exists())
-    {
-      if(!backendDirectory.mkdirs())
-      {
-        LocalizableMessage message =
-          ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath());
-        throw new ConfigException(message);
-      }
-    }
-    //Make sure the directory is valid.
-    else if (!backendDirectory.isDirectory())
-    {
-      throw new ConfigException(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()));
-    }
-
-    FilePermission backendPermission;
     try
     {
-      backendPermission =
-          FilePermission.decodeUNIXMode(config.getDBDirectoryPermissions());
-    }
-    catch(Exception e)
-    {
-      throw new ConfigException(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn()));
-    }
-
-    //Make sure the mode will allow the server itself access to
-    //the database
-    if(!backendPermission.isOwnerWritable() ||
-        !backendPermission.isOwnerReadable() ||
-        !backendPermission.isOwnerExecutable())
-    {
-      LocalizableMessage message = ERR_CONFIG_BACKEND_INSANE_MODE.get(
-          config.getDBDirectoryPermissions());
-      throw new ConfigException(message);
-    }
-
-    // Get the backend database backendDirectory permissions and apply
-    if(FilePermission.canSetPermissions())
-    {
-      try
-      {
-        if(!FilePermission.setPermissions(backendDirectory, backendPermission))
-        {
-          logger.warn(WARN_JEB_UNABLE_SET_PERMISSIONS, backendPermission, backendDirectory);
-        }
-      }
-      catch(Exception e)
-      {
-        // Log an warning that the permissions were not set.
-        logger.warn(WARN_JEB_SET_PERMISSIONS_FAILED, backendDirectory, e);
-      }
-    }
-
-    try
-    {
-      storage = (PersistItStorage) backend.newStorageInstance();
+      storage = backend.newStorageInstance();
       storage.initialize(config);
       storage.open();
       storage.write(new WriteOperation()
@@ -433,21 +366,24 @@
    * containers opened in a non transactional root container will also be non
    * transactional.
    *
-   * @param baseDN The base DN of the entry container to open.
-   * @param name The name of the entry container or <CODE>NULL</CODE> to open
-   * the default entry container for the given base DN.
-   * @param txn The database transaction
+   * @param baseDN
+   *          The base DN of the entry container to open.
+   * @param name
+   *          The name of the entry container or <CODE>NULL</CODE> to open the
+   *          default entry container for the given base DN.
+   * @param txn
+   *          The database transaction
    * @return The opened entry container.
-   * @throws StorageRuntimeException If an error occurs while opening the entry
-   *                           container.
-   * @throws ConfigException If an configuration error occurs while opening
-   *                         the entry container.
+   * @throws StorageRuntimeException
+   *           If an error occurs while opening the entry container.
+   * @throws ConfigException
+   *           If an configuration error occurs while opening the entry container.
    */
-  public EntryContainer openEntryContainer(DN baseDN, String name, WriteableStorage txn)
+  EntryContainer openEntryContainer(DN baseDN, String name, WriteableStorage txn)
       throws StorageRuntimeException, ConfigException
   {
     String databasePrefix;
-    if(name == null || name.equals(""))
+    if (name == null || "".equals(name))
     {
       databasePrefix = baseDN.toIrreversibleReadableString();
     }
@@ -456,8 +392,8 @@
       databasePrefix = name;
     }
 
-    EntryContainer ec = new EntryContainer(baseDN, storage.toSuffixName(databasePrefix),
-                                           backend, config, storage, this);
+    EntryContainer ec =
+        new EntryContainer(baseDN, storage.toSafeSuffixName(databasePrefix), backend, config, storage, this);
     ec.open(txn);
     return ec;
   }
@@ -465,13 +401,14 @@
   /**
    * Registers the entry container for a base DN.
    *
-   * @param baseDN The base DN of the entry container to close.
-   * @param entryContainer The entry container to register for the baseDN.
-   * @throws InitializationException If an error occurs while opening the
-   *                                 entry container.
+   * @param baseDN
+   *          The base DN of the entry container to close.
+   * @param entryContainer
+   *          The entry container to register for the baseDN.
+   * @throws InitializationException
+   *           If an error occurs while opening the entry container.
    */
-  public void registerEntryContainer(DN baseDN, EntryContainer entryContainer)
-      throws InitializationException
+  void registerEntryContainer(DN baseDN, EntryContainer entryContainer) throws InitializationException
   {
     EntryContainer ec1 = this.entryContainers.get(baseDN);
 
@@ -479,8 +416,8 @@
     // another to be opened.
     if (ec1 != null)
     {
-      throw new InitializationException(ERR_JEB_ENTRY_CONTAINER_ALREADY_REGISTERED.get(
-          ec1.getDatabasePrefix(), baseDN));
+      throw new InitializationException(ERR_JEB_ENTRY_CONTAINER_ALREADY_REGISTERED.get(ec1.getDatabasePrefix(),
+          baseDN));
     }
 
     this.entryContainers.put(baseDN, entryContainer);
@@ -489,24 +426,27 @@
   /**
    * Opens the entry containers for multiple base DNs.
    *
-   * @param baseDNs The base DNs of the entry containers to open.
-   * @throws StorageRuntimeException       If a database error occurs while opening
-   *                                 the entry container.
-   * @throws InitializationException If an initialization error occurs while
-   *                                 opening the entry container.
-   * @throws ConfigException         If a configuration error occurs while
-   *                                 opening the entry container.
+   * @param baseDNs
+   *          The base DNs of the entry containers to open.
+   * @throws StorageRuntimeException
+   *           If a database error occurs while opening the entry container.
+   * @throws InitializationException
+   *           If an initialization error occurs while opening the entry
+   *           container.
+   * @throws ConfigException
+   *           If a configuration error occurs while opening the entry
+   *           container.
    */
-  private void openAndRegisterEntryContainers(WriteableStorage txn, Set<DN> baseDNs)
-      throws StorageRuntimeException, InitializationException, ConfigException
+  private void openAndRegisterEntryContainers(WriteableStorage txn, Set<DN> baseDNs) throws StorageRuntimeException,
+      InitializationException, ConfigException
   {
     EntryID highestID = null;
-    for(DN baseDN : baseDNs)
+    for (DN baseDN : baseDNs)
     {
       EntryContainer ec = openEntryContainer(baseDN, null, txn);
       EntryID id = ec.getHighestEntryID(txn);
       registerEntryContainer(baseDN, ec);
-      if(highestID == null || id.compareTo(highestID) > 0)
+      if (highestID == null || id.compareTo(highestID) > 0)
       {
         highestID = id;
       }
@@ -518,11 +458,12 @@
   /**
    * Unregisters the entry container for a base DN.
    *
-   * @param baseDN The base DN of the entry container to close.
+   * @param baseDN
+   *          The base DN of the entry container to close.
    * @return The entry container that was unregistered or NULL if a entry
-   * container for the base DN was not registered.
+   *         container for the base DN was not registered.
    */
-  public EntryContainer unregisterEntryContainer(DN baseDN)
+  EntryContainer unregisterEntryContainer(DN baseDN)
   {
     return entryContainers.remove(baseDN);
   }
@@ -530,7 +471,7 @@
   /**
    * Retrieves the compressed schema manager for this backend.
    *
-   * @return  The compressed schema manager for this backend.
+   * @return The compressed schema manager for this backend.
    */
   public CompressedSchema getCompressedSchema()
   {
@@ -541,11 +482,11 @@
    * Get the DatabaseEnvironmentMonitor object for JE environment used by this
    * root container.
    *
-   * @return The DatabaseEnvironmentMonito object.
+   * @return The DatabaseEnvironmentMonitor object.
    */
   public DatabaseEnvironmentMonitor getMonitorProvider()
   {
-    if(monitor == null)
+    if (monitor == null)
     {
       String monitorName = backend.getBackendID() + " Database Storage";
       monitor = new DatabaseEnvironmentMonitor(monitorName, this);
@@ -558,9 +499,10 @@
    * Preload the database cache. There is no preload if the configured preload
    * time limit is zero.
    *
-   * @param timeLimit The time limit for the preload process.
+   * @param timeLimit
+   *          The time limit for the preload process.
    */
-  public void preload(long timeLimit)
+  void preload(long timeLimit)
   {
     if (timeLimit > 0)
     {
@@ -601,12 +543,12 @@
   /**
    * Closes this root container.
    *
-   * @throws StorageRuntimeException If an error occurs while attempting to close
-   * the root container.
+   * @throws StorageRuntimeException
+   *           If an error occurs while attempting to close the root container.
    */
-  public void close() throws StorageRuntimeException
+  void close() throws StorageRuntimeException
   {
-    for(DN baseDN : entryContainers.keySet())
+    for (DN baseDN : entryContainers.keySet())
     {
       EntryContainer ec = unregisterEntryContainer(baseDN);
       ec.exclusiveLock.lock();
@@ -621,7 +563,7 @@
     }
 
     compressedSchema.close();
-    config.removePersistitChangeListener(this);
+    config.removePluggableChangeListener(this);
 
     if (storage != null)
     {
@@ -653,10 +595,11 @@
   /**
    * Return the entry container for a specific base DN.
    *
-   * @param baseDN The base DN of the entry container to retrieve.
+   * @param baseDN
+   *          The base DN of the entry container to retrieve.
    * @return The entry container for the base DN.
    */
-  public EntryContainer getEntryContainer(DN baseDN)
+  EntryContainer getEntryContainer(DN baseDN)
   {
     EntryContainer ec = null;
     DN nodeDN = baseDN;
@@ -673,14 +616,12 @@
     return ec;
   }
 
-
-
   /**
    * Get the backend configuration used by this root container.
    *
    * @return The backend configuration used by this root container.
    */
-  public PersistitBackendCfg getConfiguration()
+  public PluggableBackendCfg getConfiguration()
   {
     return config;
   }
@@ -689,8 +630,8 @@
    * Get the total number of entries in this root container.
    *
    * @return The number of entries in this root container
-   * @throws StorageRuntimeException If an error occurs while retrieving the entry
-   *                           count.
+   * @throws StorageRuntimeException
+   *           If an error occurs while retrieving the entry count.
    */
   public long getEntryCount() throws StorageRuntimeException
   {
@@ -745,7 +686,7 @@
   }
 
   /**
-   * Resets the next entry ID counter to zero.  This should only be used after
+   * Resets the next entry ID counter to zero. This should only be used after
    * clearing all databases.
    */
   public void resetNextEntryID()
@@ -753,176 +694,28 @@
     nextid.set(1);
   }
 
-
-
   /** {@inheritDoc} */
   @Override
-  public boolean isConfigurationChangeAcceptable(
-      PersistitBackendCfg cfg,
+  public boolean isConfigurationChangeAcceptable(PluggableBackendCfg configuration,
       List<LocalizableMessage> unacceptableReasons)
   {
-    boolean acceptable = true;
-
-    File parentDirectory = getFileForPath(config.getDBDirectory());
-    File backendDirectory = new File(parentDirectory, config.getBackendId());
-
-    //Make sure the directory either already exists or is able to create.
-    if (!backendDirectory.exists())
-    {
-      if(!backendDirectory.mkdirs())
-      {
-        unacceptableReasons.add(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath()));
-        acceptable = false;
-      }
-      else
-      {
-        backendDirectory.delete();
-      }
-    }
-    //Make sure the directory is valid.
-    else if (!backendDirectory.isDirectory())
-    {
-      unacceptableReasons.add(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()));
-      acceptable = false;
-    }
-
-    try
-    {
-      FilePermission newBackendPermission =
-          FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions());
-
-      //Make sure the mode will allow the server itself access to
-      //the database
-      if(!newBackendPermission.isOwnerWritable() ||
-          !newBackendPermission.isOwnerReadable() ||
-          !newBackendPermission.isOwnerExecutable())
-      {
-        LocalizableMessage message = ERR_CONFIG_BACKEND_INSANE_MODE.get(
-            cfg.getDBDirectoryPermissions());
-        unacceptableReasons.add(message);
-        acceptable = false;
-      }
-    }
-    catch(Exception e)
-    {
-      unacceptableReasons.add(ERR_CONFIG_BACKEND_MODE_INVALID.get(cfg.dn()));
-      acceptable = false;
-    }
-
-    try
-    {
-      // FIXME JNR validate database specific configuration
-    }
-    catch (Exception e)
-    {
-      unacceptableReasons.add(LocalizableMessage.raw(e.getLocalizedMessage()));
-      acceptable = false;
-    }
-
-    return acceptable;
+    // Storage has also registered a change listener, delegate to it.
+    return true;
   }
 
-
-
   /** {@inheritDoc} */
   @Override
-  public ConfigChangeResult applyConfigurationChange(PersistitBackendCfg cfg)
+  public ConfigChangeResult applyConfigurationChange(PluggableBackendCfg configuration)
   {
-    final ConfigChangeResult ccr = new ConfigChangeResult();
+    getMonitorProvider().enableFilterUseStats(configuration.isIndexFilterAnalyzerEnabled());
+    getMonitorProvider().setMaxEntries(configuration.getIndexFilterAnalyzerMaxFilters());
 
-    try
-    {
-      // Create the directory if it doesn't exist.
-      if(!cfg.getDBDirectory().equals(this.config.getDBDirectory()))
-      {
-        File parentDirectory = getFileForPath(cfg.getDBDirectory());
-        File backendDirectory =
-          new File(parentDirectory, cfg.getBackendId());
-
-        if (!backendDirectory.exists())
-        {
-          if(!backendDirectory.mkdirs())
-          {
-            ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
-            ccr.addMessage(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath()));
-            return ccr;
-          }
-        }
-        //Make sure the directory is valid.
-        else if (!backendDirectory.isDirectory())
-        {
-          ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
-          ccr.addMessage(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()));
-          return ccr;
-        }
-
-        ccr.setAdminActionRequired(true);
-        ccr.addMessage(NOTE_JEB_CONFIG_DB_DIR_REQUIRES_RESTART.get(this.config.getDBDirectory(), cfg.getDBDirectory()));
-      }
-
-      if (!cfg.getDBDirectoryPermissions().equalsIgnoreCase(config.getDBDirectoryPermissions())
-          || !cfg.getDBDirectory().equals(this.config.getDBDirectory()))
-      {
-        FilePermission backendPermission;
-        try
-        {
-          backendPermission =
-              FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions());
-        }
-        catch(Exception e)
-        {
-          ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
-          ccr.addMessage(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn()));
-          return ccr;
-        }
-
-        // Make sure the mode will allow the server itself access to the database
-        if(!backendPermission.isOwnerWritable() ||
-            !backendPermission.isOwnerReadable() ||
-            !backendPermission.isOwnerExecutable())
-        {
-          ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
-          ccr.addMessage(ERR_CONFIG_BACKEND_INSANE_MODE.get(cfg.getDBDirectoryPermissions()));
-          return ccr;
-        }
-
-        // Get the backend database backendDirectory permissions and apply
-        if(FilePermission.canSetPermissions())
-        {
-          File parentDirectory = getFileForPath(config.getDBDirectory());
-          File backendDirectory = new File(parentDirectory, config.getBackendId());
-          try
-          {
-            if (!FilePermission.setPermissions(backendDirectory, backendPermission))
-            {
-              logger.warn(WARN_JEB_UNABLE_SET_PERMISSIONS, backendPermission, backendDirectory);
-            }
-          }
-          catch(Exception e)
-          {
-            // Log an warning that the permissions were not set.
-            logger.warn(WARN_JEB_SET_PERMISSIONS_FAILED, backendDirectory, e);
-          }
-        }
-      }
-
-      getMonitorProvider().enableFilterUseStats(cfg.isIndexFilterAnalyzerEnabled());
-      getMonitorProvider().setMaxEntries(cfg.getIndexFilterAnalyzerMaxFilters());
-
-      this.config = cfg;
-    }
-    catch (Exception e)
-    {
-      ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
-      ccr.addMessage(LocalizableMessage.raw(stackTraceToSingleLineString(e)));
-      return ccr;
-    }
-    return ccr;
+    return new ConfigChangeResult();
   }
 
   /**
-   * Returns whether this container JE database environment is
-   * open, valid and can be used.
+   * Returns whether this container JE database environment is open, valid and
+   * can be used.
    *
    * @return {@code true} if valid, or {@code false} otherwise.
    */
diff --git a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
index 2d82a69..d556490 100644
--- a/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
+++ b/opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
@@ -115,4 +115,20 @@
   /** {@inheritDoc} */
   @Override
   void close();
-}
\ No newline at end of file
+
+  /**
+   * Remove all files for a backend of this storage.
+   *
+   * @throws StorageRuntimeException if removal fails
+   */
+  void removeStorageFiles() throws StorageRuntimeException;
+
+  /**
+   * Replace reserved characters with an underscore character.
+   *
+   * @param databasePrefix
+   *          the suffix name to convert
+   * @return a new String suitable for use as a suffix name
+   */
+  String toSafeSuffixName(String databasePrefix);
+}

--
Gitblit v1.10.0