mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noël Rouvignac
19.03.2016 17ec2cfa9d04e6942a694ab5c3778ac26f17bb35
opendj-server-legacy/src/main/java/org/opends/server/backends/MemoryBackend.java
@@ -26,12 +26,14 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.schema.AttributeType;
@@ -48,7 +50,6 @@
import org.opends.server.types.BackupConfig;
import org.opends.server.types.BackupDirectory;
import org.opends.server.types.Control;
import org.forgerock.opendj.ldap.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.IndexType;
@@ -95,23 +96,16 @@
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  /** The set of supported controls for this backend. */
  private static final Set<String> supportedControls = Collections.singleton(OID_SUBTREE_DELETE_CONTROL);
  /** The base DNs for this backend. */
  private Set<DN> baseDNs;
  /** The mapping between parent DNs and their immediate children. */
  private HashMap<DN,HashSet<DN>> childDNs;
  /** The set of supported controls for this backend. */
  private final Set<String> supportedControls =
      Collections.singleton(OID_SUBTREE_DELETE_CONTROL);
  private Map<DN, HashSet<DN>> childDNs;
  /** The mapping between entry DNs and the corresponding entries. */
  private LinkedHashMap<DN,Entry> entryMap;
  /**
   * Creates a new backend with the provided information.  All backend
   * implementations must implement a default constructor that use
@@ -124,7 +118,6 @@
    // Perform all initialization in initializeBackend.
  }
  /**
   * Set the base DNs for this backend.  This is used by the unit tests
   * to set the base DNs without having to provide a configuration
@@ -177,18 +170,13 @@
    }
  }
  /**
   * Removes any data that may have been stored in this backend.
   */
  /** Removes any data that may have been stored in this backend. */
  public synchronized void clearMemoryBackend()
  {
    entryMap.clear();
    childDNs.clear();
  }
  /** {@inheritDoc} */
  @Override
  public synchronized void closeBackend()
  {
@@ -224,7 +212,6 @@
    return -1;
  }
  /** {@inheritDoc} */
  @Override
  public boolean isIndexed(AttributeType attributeType, IndexType indexType)
  {
@@ -232,7 +219,6 @@
    return true;
  }
  /** {@inheritDoc} */
  @Override
  public synchronized ConditionResult hasSubordinates(DN entryDN)
         throws DirectoryException
@@ -245,14 +231,12 @@
    return ConditionResult.valueOf(ret != 0);
  }
  /** {@inheritDoc} */
  @Override
  public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException {
    checkNotNull(baseDN, "baseDN must not be null");
    return getNumberOfSubordinates(baseDN, true) + 1;
  }
  /** {@inheritDoc} */
  @Override
  public long getNumberOfChildren(DN parentDN) throws DirectoryException {
    checkNotNull(parentDN, "parentDN must not be null");
@@ -286,7 +270,6 @@
    return count;
  }
  /** {@inheritDoc} */
  @Override
  public synchronized Entry getEntry(DN entryDN)
  {
@@ -299,14 +282,12 @@
    return entry;
  }
  /** {@inheritDoc} */
  @Override
  public synchronized boolean entryExists(DN entryDN)
  {
    return entryMap.containsKey(entryDN);
  }
  /** {@inheritDoc} */
  @Override
  public synchronized void addEntry(Entry entry, AddOperation addOperation)
         throws DirectoryException
@@ -321,7 +302,6 @@
          ERR_MEMORYBACKEND_ENTRY_ALREADY_EXISTS.get(entryDN));
    }
    // If the entry is one of the base DNs, then add it.
    if (baseDNs.contains(entryDN))
    {
@@ -329,7 +309,6 @@
      return;
    }
    // Get the parent DN and ensure that it exists in the backend.
    DN parentDN = DirectoryServer.getParentDNInSuffix(entryDN);
    if (parentDN == null)
@@ -354,7 +333,6 @@
    children.add(entryDN);
  }
  /** {@inheritDoc} */
  @Override
  public synchronized void deleteEntry(DN entryDN,
                                       DeleteOperation deleteOperation)
@@ -367,41 +345,34 @@
          ERR_BACKEND_ENTRY_DOESNT_EXIST.get(entryDN, getBackendID()));
    }
    // Check to see if the entry contains a subtree delete control.
    boolean subtreeDelete = deleteOperation != null
        && deleteOperation.getRequestControl(SubtreeDeleteControl.DECODER) != null;
    HashSet<DN> children = childDNs.get(entryDN);
    if (subtreeDelete)
    Set<DN> children = childDNs.get(entryDN);
    if (children != null && !children.isEmpty())
    {
      if (children != null)
      {
        HashSet<DN> childrenCopy = new HashSet<>(children);
        for (DN childDN : childrenCopy)
        {
          try
          {
            deleteEntry(childDN, null);
          }
          catch (Exception e)
          {
            // This shouldn't happen, but we want the delete to continue anyway
            // so just ignore it if it does for some reason.
            logger.traceException(e);
          }
        }
      }
    }
    else
    {
      // Make sure the entry doesn't have any children.  If it does, then throw
      // an exception.
      if (children != null && !children.isEmpty())
      // children exist
      if (!subtreeDelete)
      {
        throw new DirectoryException(ResultCode.NOT_ALLOWED_ON_NONLEAF,
            ERR_MEMORYBACKEND_CANNOT_DELETE_ENTRY_WITH_CHILDREN.get(entryDN));
      }
      Set<DN> childrenCopy = new HashSet<>(children);
      for (DN childDN : childrenCopy)
      {
        try
        {
          deleteEntry(childDN, null);
        }
        catch (Exception ignore)
        {
          // This shouldn't happen, but we want the delete to continue anyway
          // so just ignore it if it does for some reason.
          logger.traceException(ignore);
        }
      }
    }
@@ -425,7 +396,6 @@
    }
  }
  /** {@inheritDoc} */
  @Override
  public synchronized void replaceEntry(Entry oldEntry, Entry newEntry,
      ModifyOperation modifyOperation) throws DirectoryException
@@ -440,12 +410,10 @@
          ERR_BACKEND_ENTRY_DOESNT_EXIST.get(entryDN, getBackendID()));
    }
    // Replace the old entry with the new one.
    entryMap.put(entryDN, e);
  }
  /** {@inheritDoc} */
  @Override
  public synchronized void renameEntry(DN currentDN, Entry entry,
                                       ModifyDNOperation modifyDNOperation)
@@ -460,9 +428,8 @@
          ERR_BACKEND_ENTRY_DOESNT_EXIST.get(currentDN, getBackendID()));
    }
    // Make sure that the target entry doesn't have any children.
    HashSet<DN> children  = childDNs.get(currentDN);
    Set<DN> children = childDNs.get(currentDN);
    if (children != null)
    {
      if (children.isEmpty())
@@ -476,7 +443,6 @@
      }
    }
    // Make sure that no entry exists with the new DN.
    if (entryMap.containsKey(e.getName()))
    {
@@ -484,25 +450,13 @@
          ERR_MEMORYBACKEND_ENTRY_ALREADY_EXISTS.get(e.getName()));
    }
    // Make sure that the new DN is in this backend.
    boolean matchFound = false;
    for (DN dn : baseDNs)
    {
      if (dn.isSuperiorOrEqualTo(e.getName()))
      {
        matchFound = true;
        break;
      }
    }
    if (! matchFound)
    if (!superiorExistsInBackend(e.getName()))
    {
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
          ERR_MEMORYBACKEND_CANNOT_RENAME_TO_ANOTHER_BACKEND.get(currentDN));
    }
    // Make sure that the parent of the new entry exists.
    DN parentDN = DirectoryServer.getParentDNInSuffix(e.getName());
    if (parentDN == null || !entryMap.containsKey(parentDN))
@@ -511,13 +465,23 @@
          ERR_MEMORYBACKEND_RENAME_PARENT_DOESNT_EXIST.get(currentDN, parentDN));
    }
    // Delete the current entry and add the new one.
    deleteEntry(currentDN, null);
    addEntry(e, null);
  }
  /** {@inheritDoc} */
  private boolean superiorExistsInBackend(DN dnToFind)
  {
    for (DN dn : baseDNs)
    {
      if (dn.isSuperiorOrEqualTo(dnToFind))
      {
        return true;
      }
    }
    return false;
  }
  @Override
  public synchronized void search(SearchOperation searchOperation)
         throws DirectoryException
@@ -527,7 +491,6 @@
    SearchScope  scope  = searchOperation.getScope();
    SearchFilter filter = searchOperation.getFilter();
    // Make sure the base entry exists if it's supposed to be in this backend.
    Entry baseEntry = entryMap.get(baseDN);
    if (baseEntry == null && handlesEntry(baseDN))
@@ -554,7 +517,6 @@
      baseEntry = baseEntry.duplicate(true);
    }
    // If it's a base-level search, then just get that entry and return it if it
    // matches the filter.
    if (scope == SearchScope.BASE_OBJECT)
@@ -578,21 +540,18 @@
    }
  }
  /** {@inheritDoc} */
  @Override
  public Set<String> getSupportedControls()
  {
    return supportedControls;
  }
  /** {@inheritDoc} */
  @Override
  public Set<String> getSupportedFeatures()
  {
    return Collections.emptySet();
  }
  /** {@inheritDoc} */
  @Override
  public boolean supports(BackendOperation backendOperation)
  {
@@ -607,7 +566,6 @@
    }
  }
  /** {@inheritDoc} */
  @Override
  public synchronized void exportLDIF(LDIFExportConfig exportConfig)
         throws DirectoryException
@@ -626,7 +584,6 @@
          ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_WRITER.get(e), e);
    }
    // Walk through all the entries and write them to LDIF.
    DN entryDN = null;
    try
@@ -648,26 +605,14 @@
    }
  }
  /** {@inheritDoc} */
  @Override
  public synchronized LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext)
      throws DirectoryException
  {
    clearMemoryBackend();
    LDIFReader reader;
    try
    {
      reader = new LDIFReader(importConfig);
    }
    catch (Exception e)
    {
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_READER.get(e), e);
    }
    try
    try (LDIFReader reader = newLDIFReader(importConfig))
    {
      while (true)
      {
@@ -687,10 +632,7 @@
            throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                ERR_MEMORYBACKEND_ERROR_READING_LDIF.get(e), le);
          }
          else
          {
            continue;
          }
          continue;
        }
        try
@@ -716,13 +658,21 @@
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          ERR_MEMORYBACKEND_ERROR_DURING_IMPORT.get(e), e);
    }
    finally
  }
  private LDIFReader newLDIFReader(LDIFImportConfig importConfig) throws DirectoryException
  {
    try
    {
      reader.close();
      return new LDIFReader(importConfig);
    }
    catch (Exception e)
    {
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_READER.get(e), e);
    }
  }
  /** {@inheritDoc} */
  @Override
  public void createBackup(BackupConfig backupConfig)
         throws DirectoryException
@@ -731,7 +681,6 @@
    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
  }
  /** {@inheritDoc} */
  @Override
  public void removeBackup(BackupDirectory backupDirectory,
                           String backupID)
@@ -741,7 +690,6 @@
    throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
  }
  /** {@inheritDoc} */
  @Override
  public void restoreBackup(RestoreConfig restoreConfig)
         throws DirectoryException