예제 #1
0
  /** {@inheritDoc} */
  @Override
  public Entry getEntry(DN entryDN) throws DirectoryException {
    // If the requested entry was null, then throw an exception.
    if (entryDN == null) {
      throw new DirectoryException(
          DirectoryServer.getServerErrorResultCode(),
          ERR_BACKEND_GET_ENTRY_NULL.get(getBackendID()));
    }

    // If the requested entry was the backend base entry, then retrieve it.
    if (entryDN.equals(backupBaseDN)) {
      return backupBaseEntry.duplicate(true);
    }

    // See if the requested entry was one level below the backend base entry.
    // If so, then it must point to a backup directory.  Otherwise, it must be
    // two levels below the backup base entry and must point to a specific
    // backup.
    DN parentDN = entryDN.getParentDNInSuffix();
    if (parentDN == null) {
      Message message = ERR_BACKUP_INVALID_BASE.get(String.valueOf(entryDN));
      throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message);
    } else if (parentDN.equals(backupBaseDN)) {
      return getBackupDirectoryEntry(entryDN);
    } else if (backupBaseDN.equals(parentDN.getParentDNInSuffix())) {
      return getBackupEntry(entryDN);
    } else {
      Message message = ERR_BACKUP_INVALID_BASE.get(String.valueOf(entryDN));
      throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, backupBaseDN, null);
    }
  }
예제 #2
0
  /**
   * If the entry has changed its name, make the required calls to set up the display tree and make
   * the directory changes.
   *
   * @param oldEntry the old entry containing teh old set of attributes.
   * @param newEntry the new entry containing the replacement set of attributes.
   */
  private boolean handleAnyNameChange(DXEntry oldEntry, DXEntry newEntry) {
    // check for 'simple' rename from the tree, with no attributes involved.
    RDN oldRDN = oldEntry.getRDN();
    RDN newRDN = newEntry.getRDN();

    DN oldDN = oldEntry.getDN();
    DN newDN = newEntry.getDN();

    if (oldDN.equals(newDN)) return true; // nothing to see here, just move along.

    if (oldEntry.size() == 0
        && newEntry.size() == 0) // a very simple rename, probably from the tree
    {
      return moveTree(oldDN, newDN);
    } else if (oldRDN.isMultiValued() == false && newRDN.isMultiValued() == false) {
      return renameSingleValuedRDNS(oldEntry, newEntry);
    } else {
      return renameComplexMultiValuedRDNs(oldEntry, newEntry);
    }
  }
예제 #3
0
 /**
  * Test the attribute types of the search filter for access. This method supports the search
  * right.
  *
  * @param container The container used in the access evaluation.
  * @param filter The filter to check access on.
  * @return True if all attribute types in the filter have access.
  * @throws DirectoryException If there is a problem matching the entry using the provided filter.
  */
 private boolean testFilter(AciLDAPOperationContainer container, SearchFilter filter)
     throws DirectoryException {
   boolean ret = true;
   // If the resource entry has a dn equal to "cn=debugsearch" and it
   // contains the special attribute type "debugsearchindex", then the
   // resource entry is a pseudo entry created for debug purposes.
   // Return true if that is the case.
   if (debugSearchIndexDN.equals(container.getResourceDN())
       && container.getResourceEntry().hasAttribute(debugSearchIndex)) {
     return true;
   }
   switch (filter.getFilterType()) {
     case AND:
     case OR:
       {
         for (SearchFilter f : filter.getFilterComponents()) {
           if (!testFilter(container, f)) {
             return false;
           }
         }
         break;
       }
     case NOT:
       {
         SearchFilter f = filter.getNotComponent();
         ret = testFilter(container, f);
         break;
       }
     default:
       {
         AttributeType attrType = filter.getAttributeType();
         container.setCurrentAttributeType(attrType);
         ret = accessAllowed(container);
       }
   }
   return ret;
 }
예제 #4
0
  /**
   * Check access using the specified container. This container will have all of the information to
   * gather applicable ACIs and perform evaluation on them.
   *
   * @param container An ACI operation container which has all of the information needed to check
   *     access.
   * @return True if access is allowed.
   */
  boolean accessAllowed(AciContainer container) {
    DN dn = container.getResourceEntry().getDN();
    // For ACI_WRITE_ADD and ACI_WRITE_DELETE set the ACI_WRITE
    // right.
    if (container.hasRights(ACI_WRITE_ADD) || container.hasRights(ACI_WRITE_DELETE)) {
      container.setRights(container.getRights() | ACI_WRITE);
    }
    // Check if the ACI_SELF right needs to be set (selfwrite right).
    // Only done if the right is ACI_WRITE, an attribute value is set
    // and that attribute value is a DN.
    if ((container.getCurrentAttributeValue() != null)
        && (container.hasRights(ACI_WRITE))
        && (isAttributeDN(container.getCurrentAttributeType()))) {
      String DNString = null;
      try {
        DNString = container.getCurrentAttributeValue().getValue().toString();
        DN tmpDN = DN.decode(DNString);
        // Have a valid DN, compare to clientDN to see if the ACI_SELF
        // right should be set.
        if (tmpDN.equals(container.getClientDN())) {
          container.setRights(container.getRights() | ACI_SELF);
        }
      } catch (DirectoryException ex) {
        // Log a message and keep going.
        Message message = WARN_ACI_NOT_VALID_DN.get(DNString);
        logError(message);
      }
    }

    // Check proxy authorization only if the entry has not already been
    // processed (working on a new entry). If working on a new entry,
    // then only do a proxy check if the right is not set to ACI_PROXY
    // and the proxied authorization control has been decoded.
    if (!container.hasSeenEntry()) {
      if (container.isProxiedAuthorization()
          && !container.hasRights(ACI_PROXY)
          && !container.hasRights(ACI_SKIP_PROXY_CHECK)) {
        int currentRights = container.getRights();
        // Save the current rights so they can be put back if on
        // success.
        container.setRights(ACI_PROXY);
        // Switch to the original authorization entry, not the proxied
        // one.
        container.useOrigAuthorizationEntry(true);
        if (!accessAllowed(container)) {
          return false;
        }
        // Access is ok, put the original rights back.
        container.setRights(currentRights);
        // Put the proxied authorization entry back to the current
        // authorization entry.
        container.useOrigAuthorizationEntry(false);
      }
      // Set the seen flag so proxy processing is not performed for this
      // entry again.
      container.setSeenEntry(true);
    }

    /*
     * First get all allowed candidate ACIs.
     */
    LinkedList<Aci> candidates = aciList.getCandidateAcis(dn);
    /*
     * Create an applicable list of ACIs by target matching each
     * candidate ACI against the container's target match view.
     */
    createApplicableList(candidates, container);
    /*
     * Evaluate the applicable list.
     */
    boolean ret = testApplicableLists(container);
    // Build summary string if doing geteffectiverights eval.
    if (container.isGetEffectiveRightsEval()) {
      AciEffectiveRights.createSummary(container, ret, "main");
    }
    return ret;
  }
예제 #5
0
  /**
   * Updates the config file during the upgrade process.
   *
   * @param configPath The original path to the file.
   * @param filter The filter to select entries. Only useful for modify change type.
   * @param changeType The change type which must be applied to ldif lines.
   * @param ldifLines The change record ldif lines. For ADD change type, the first line must be the
   *     dn. For DELETE change type, the first and only line must be the dn.
   * @throws IOException If an Exception occurs during the input output methods.
   * @return The changes number that have occurred.
   */
  static int updateConfigFile(
      final String configPath,
      final Filter filter,
      final ChangeOperationType changeType,
      final String... ldifLines)
      throws IOException {
    final File original = new File(configPath);
    final File copyConfig = File.createTempFile("copyConfig", ".tmp", original.getParentFile());

    int changeCount = 0;
    LDIFEntryReader entryReader = null;
    LDIFEntryWriter writer = null;
    try {
      final Schema schema = getUpgradeSchema();
      entryReader = new LDIFEntryReader(new FileInputStream(configPath)).setSchema(schema);

      writer = new LDIFEntryWriter(new FileOutputStream(copyConfig));
      writer.setWrapColumn(80);

      // Writes the header on the new file.
      writer.writeComment(INFO_CONFIG_FILE_HEADER.get());
      writer.setWrapColumn(0);

      boolean entryAlreadyExist = false;
      DN ldifDN = null;
      if (filter == null && (changeType == ADD || changeType == DELETE)) {
        // The first line should start with dn:
        ldifDN = DN.valueOf(ldifLines[0].replaceFirst("dn: ", ""));
      }
      final Filter f = filter != null ? filter : Filter.alwaysFalse();
      final Matcher matcher = f.matcher(schema);
      while (entryReader.hasNext()) {
        Entry entry = entryReader.readEntry();
        final DN entryDN = entry.getName();
        // Searching for the related entries
        if (changeType == MODIFY && matcher.matches(entry) == ConditionResult.TRUE) {
          try {
            final ModifyRequest mr =
                Requests.newModifyRequest(readLDIFLines(entryDN, changeType, ldifLines));
            entry = Entries.modifyEntryPermissive(entry, mr.getModifications());
            changeCount++;
            logger.debug(
                LocalizableMessage.raw("The following entry has been modified : %s", entryDN));
          } catch (Exception ex) {
            logger.error(LocalizableMessage.raw(ex.getMessage()));
          }
        }

        if (entryDN.equals(ldifDN)) {
          logger.debug(LocalizableMessage.raw("Entry %s found", entryDN));
          entryAlreadyExist = true;

          if (changeType == DELETE) {
            entry = null;
            changeCount++;
            logger.debug(
                LocalizableMessage.raw("The following entry has been deleted : %s", entryDN));
          }
        }

        if (entry != null) {
          writer.writeEntry(entry);
        }
      }

      if (changeType == ADD && !entryAlreadyExist) {
        final AddRequest ar = Requests.newAddRequest(ldifLines);
        writer.writeEntry(ar);
        logger.debug(
            LocalizableMessage.raw(
                "Entry successfully added %s in %s", ldifDN, original.getAbsolutePath()));
        changeCount++;
      }
    } catch (Exception ex) {
      throw new IOException(ex.getMessage());
    } finally {
      // The reader and writer must be close before renaming files.
      // Otherwise it causes exceptions under windows OS.
      StaticUtils.close(entryReader, writer);
    }

    try {
      // Renaming the file, overwriting previous one.
      rename(copyConfig, new File(configPath));
    } catch (IOException e) {
      logger.error(LocalizableMessage.raw(e.getMessage()));
      deleteRecursively(original);
      throw e;
    }

    return changeCount;
  }
예제 #6
0
  private void displayEntry(
      DXEntry entry, DataBrokerQueryInterface ds, boolean storeOriginalEntry) {
    myEditor.stopCellEditing();

    //        checkedDN = null; // hack - resets promptForSave.
    // Store original Entry for reset
    if (entry != null && storeOriginalEntry && entry.getStatus() == DXEntry.NORMAL)
      originalEntry = new DXEntry(entry);

    // Set the globals...
    currentEntry = entry;
    dataSource = ds;

    if (entry != null && entry.size() == 0) {
      // If there is an entry and its size is zero - it's probably a virtual entry.
      // We need to give the user the option of adding an object class to it i.e. so that
      // it can be added to the directory as a real entry.
      //
      // Disable all the buttons except the 'Change Class' button - but rename this button
      // to 'Add Class' so the user hopefully has a bit more of an idea about what is going on.

      // Sets editor to a blank screen...
      tableData.clear();

      // Disable all buttons except the 'Change Class' button - rename this one...
      submit.setEnabled(false);
      reset.setEnabled(false);
      changeClass.setText(CBIntText.get("Add Class"));
      changeClass.setEnabled(true);
      opAttrs.setEnabled(false);

      virtualEntry = true;

      return;
    }

    virtualEntry = false;

    // Isn't a virtual entry...
    if (entry != null) currentDN = entry.getDN();

    // May have been changed to 'Add Class'...
    changeClass.setText(CBIntText.get("Change Class"));

    // Some quick faffing around, to see if we're coming back from a
    // change classes operation.
    if (classChangedOriginalEntry != null) {
      // If they have the same name, then we're reviewing the same entry - otherwise we've moved on
      if (entry == null || entry.getDN().equals(classChangedOriginalEntry.getDN()) == false)
        classChangedOriginalEntry = null;
    }

    /*
     *    Check that we're not displaying a new entry, and leaving unsaved changes
     *    behind.
     *
     *    This turns out to be quite tricky, and involves a bunch 'o special cases.
     *
     *    First check whether the table data has changed (if not, do nothing)
     *    ->  if the new entry is null, prompt user to save
     *    ->  OR if the DN has changed, and it wasn't due to a rename, prompt user to save
     *
     */
    if (tableData.changedByUser()) // user made changes - were they saved?  (i.e., are we
    { // displaying the result of those changes?)
      boolean prompt = false;

      DXEntry oldEntry = tableData.getOldEntry();

      if (oldEntry != null) {
        /*
         *    The code below is simply checking to see if the name of the
         *    new entry is different from the old entry, and if it is,
         *    whether that's due to the old entry being renamed.
         */
        if (entry == null) {
          prompt = true;
        }
        // TE: added the isEmpty check see bug: 3194.
        else if (!oldEntry.getDN().isEmpty() && entry.getDN().equals(oldEntry.getDN()) == false) {
          DN oldParent = oldEntry.getDN().getParent();

          DN newParent = entry.getDN().getParent();

          if (oldParent.equals(newParent) == false) {
            prompt = true;
          } else {
            if (entry.getDN().getLowestRDN().equals(tableData.getRDN()) == false) {
              prompt = true;
            }
          }
        }

        if (prompt) // yes, there is a risk of data loss - prompt the user.
        {
          checkForUnsavedChanges(); // see if the user wants to save their data
        }
      }
    }

    myEditor.setDataSource(
        ds); // Sets the DataBrokerQueryInterface in AttributeValueCellEditor used to get the syntax
             // of attributes.

    // only enable buttons if DataBrokerQueryInterface
    // is valid *and* we can modify data...

    if (dataSource == null || entry == null || dataSource.isModifiable() == false) {
      setReadWrite(false, entry);
    } else {
      setReadWrite(true, entry);
    }

    //        myEditor.stopCellEditing();

    if (entry != null) {
      entry.expandAllAttributes();
      currentDN = entry.getDN();

      tableData.insertAttributes(entry);
      popupTableTool.setDN(currentDN); // Sets the DN in SmartPopupTableTool.
      myEditor.setDN(
          currentDN); // Sets the DN in the attributeValueCellEditor which can be used to identify
                      // the entry that is being modified/
    } else {
      tableData.clear(); // Sets editor to a blank screen.
    }

    tableScroller.getVerticalScrollBar().setValue(0); // Sets the scroll bar back to the top.
  }
예제 #7
0
  /** Opens the change class dialog. */
  public void changeClass() { // JPanel mainPanel
    /*
     *    MINOR MAGIC
     *
     *    This code reuses the 'new entry window'.  In order to make things
     *    sane, we prompt the user to save any serious changes before continuing.
     *    (Things can get really wierd if the user changes the name and then
     *    tries to change the objectclass - best to avoid the whole issue.)
     */
    myEditor.stopCellEditing();

    if (virtualEntry) {
      doVirtualEntryDisplay();
      return;
    }

    /*
     *    classChangedOriginalEntry saves the original state of the entry
     *    between visits to NewEntryWin.  (- I wonder if it would be neater
     *    to just reset the 'oldEntry' state of the table every time? ).
     *    Check it's not been set already (i.e. Pathological User is paying
     *    multiple visits to the NewEntryWin.)
     */
    if (classChangedOriginalEntry == null) classChangedOriginalEntry = tableData.getOldEntry();

    DXEntry newEntry = tableData.getNewEntry();
    DN newDN = newEntry.getDN();

    /*
     *    Pathalogical user has messed with the name, *and* wants to
     *    change the object classes...
     */
    if (newDN.equals(classChangedOriginalEntry.getDN()) == false) {
      checkForUnsavedChanges();
      /*
      if (promptForSave() == false)  // we may need to reset the 'newEntry' data
      {                                   // if the user discards their changes.

          tableData.reset();              // resets the table before going on.

          newEntry = tableData.getNewEntry();
          newDN = newEntry.getDN();
      }
      else // user has saved data - so now we need to reset the 'classChangedOriginalEntry'
      {
      */
      // to the changed (and hopefully saved!) data.
      // NB: If the directory write fails, then the change classes will also fail...
      classChangedOriginalEntry = tableData.getNewEntry();
    }

    /*
     *    Open NewEntryWin, allowing the user to reset the objectclass attribute.
     */

    /*
            NewEntryWin userData = new NewEntryWin(newDN.parentDN(), newDN,
                                    dataSource,
                                    newEntry.getAsNonNullAttributes(),
                                    newDN.getLowestRDN().toString(), TableAttributeEditor.this,
                                    CBUtility.getParentFrame(mainPanel));
    */
    if (dataSource.getSchemaOps() == null) {
      JOptionPane.showMessageDialog(
          owner,
          CBIntText.get(
              "Because there is no schema currently published by the\ndirectory, changing an entry's object class is unavailable."),
          CBIntText.get("No Schema"),
          JOptionPane.INFORMATION_MESSAGE);
      return;
    } else {
      ChangeObjectClassWin userData =
          new ChangeObjectClassWin(
              dataSource,
              newDN,
              newEntry.getAsNonNullAttributes(),
              this,
              CBUtility.getParentFrame(this),
              false);
      userData.setSize(400, 250);
      CBUtility.center(userData, owner); // TE: centres window.
      userData.setVisible(true);
    }
  }
예제 #8
0
  /** {@inheritDoc} */
  @Override
  public void search(SearchOperation searchOperation) throws DirectoryException {
    // Get the base entry for the search, if possible.  If it doesn't exist,
    // then this will throw an exception.
    DN baseDN = searchOperation.getBaseDN();
    Entry baseEntry = getEntry(baseDN);

    // Look at the base DN and see if it's the backup base DN, a backup
    // directory entry DN, or a backup entry DN.
    DN parentDN;
    SearchScope scope = searchOperation.getScope();
    SearchFilter filter = searchOperation.getFilter();
    if (backupBaseDN.equals(baseDN)) {
      if ((scope == SearchScope.BASE_OBJECT || scope == SearchScope.WHOLE_SUBTREE)
          && filter.matchesEntry(baseEntry)) {
        searchOperation.returnEntry(baseEntry, null);
      }

      if (scope != SearchScope.BASE_OBJECT && !backupDirectories.isEmpty()) {
        AttributeType backupPathType =
            DirectoryServer.getAttributeType(ATTR_BACKUP_DIRECTORY_PATH, true);
        for (File f : backupDirectories) {
          // Check to see if the descriptor file exists.  If not, then skip this
          // backup directory.
          File descriptorFile = new File(f, BACKUP_DIRECTORY_DESCRIPTOR_FILE);
          if (!descriptorFile.exists()) {
            continue;
          }

          DN backupDirDN = makeChildDN(backupBaseDN, backupPathType, f.getAbsolutePath());

          Entry backupDirEntry;
          try {
            backupDirEntry = getBackupDirectoryEntry(backupDirDN);
          } catch (Exception e) {
            if (debugEnabled()) {
              TRACER.debugCaught(DebugLogLevel.ERROR, e);
            }

            continue;
          }

          if (filter.matchesEntry(backupDirEntry)) {
            searchOperation.returnEntry(backupDirEntry, null);
          }

          if (scope != SearchScope.SINGLE_LEVEL) {
            List<Attribute> attrList = backupDirEntry.getAttribute(backupPathType);
            if (attrList != null && !attrList.isEmpty()) {
              for (AttributeValue v : attrList.get(0)) {
                try {
                  BackupDirectory backupDirectory =
                      BackupDirectory.readBackupDirectoryDescriptor(v.getValue().toString());
                  AttributeType idType = DirectoryServer.getAttributeType(ATTR_BACKUP_ID, true);
                  for (String backupID : backupDirectory.getBackups().keySet()) {
                    DN backupEntryDN = makeChildDN(backupDirDN, idType, backupID);
                    Entry backupEntry = getBackupEntry(backupEntryDN);
                    if (filter.matchesEntry(backupEntry)) {
                      searchOperation.returnEntry(backupEntry, null);
                    }
                  }
                } catch (Exception e) {
                  if (debugEnabled()) {
                    TRACER.debugCaught(DebugLogLevel.ERROR, e);
                  }

                  continue;
                }
              }
            }
          }
        }
      }
    } else if (backupBaseDN.equals(parentDN = baseDN.getParentDNInSuffix())) {
      Entry backupDirEntry = getBackupDirectoryEntry(baseDN);

      if ((scope == SearchScope.BASE_OBJECT || scope == SearchScope.WHOLE_SUBTREE)
          && filter.matchesEntry(backupDirEntry)) {
        searchOperation.returnEntry(backupDirEntry, null);
      }

      if (scope != SearchScope.BASE_OBJECT) {
        AttributeType t = DirectoryServer.getAttributeType(ATTR_BACKUP_DIRECTORY_PATH, true);
        List<Attribute> attrList = backupDirEntry.getAttribute(t);
        if (attrList != null && !attrList.isEmpty()) {
          for (AttributeValue v : attrList.get(0)) {
            try {
              BackupDirectory backupDirectory =
                  BackupDirectory.readBackupDirectoryDescriptor(v.getValue().toString());
              AttributeType idType = DirectoryServer.getAttributeType(ATTR_BACKUP_ID, true);
              for (String backupID : backupDirectory.getBackups().keySet()) {
                DN backupEntryDN = makeChildDN(baseDN, idType, backupID);
                Entry backupEntry = getBackupEntry(backupEntryDN);
                if (filter.matchesEntry(backupEntry)) {
                  searchOperation.returnEntry(backupEntry, null);
                }
              }
            } catch (Exception e) {
              if (debugEnabled()) {
                TRACER.debugCaught(DebugLogLevel.ERROR, e);
              }

              continue;
            }
          }
        }
      }
    } else {
      if (parentDN == null || !backupBaseDN.equals(parentDN.getParentDNInSuffix())) {
        Message message = ERR_BACKUP_NO_SUCH_ENTRY.get(String.valueOf(backupBaseDN));
        throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message);
      }

      if (scope == SearchScope.BASE_OBJECT || scope == SearchScope.WHOLE_SUBTREE) {
        Entry backupEntry = getBackupEntry(baseDN);
        if (backupEntry == null) {
          Message message = ERR_BACKUP_NO_SUCH_ENTRY.get(String.valueOf(backupBaseDN));
          throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message);
        }

        if (filter.matchesEntry(backupEntry)) {
          searchOperation.returnEntry(backupEntry, null);
        }
      }
    }
  }
예제 #9
0
  /** {@inheritDoc} */
  @Override
  public long numSubordinates(DN entryDN, boolean subtree) throws DirectoryException {
    // If the requested entry was null, then return undefined.
    if (entryDN == null) {
      return -1;
    }

    // If the requested entry was the backend base entry, then return
    // the number of backup directories.
    if (backupBaseDN.equals(entryDN)) {
      long count = 0;
      for (File f : backupDirectories) {
        // Check to see if the descriptor file exists.  If not, then skip this
        // backup directory.
        File descriptorFile = new File(f, BACKUP_DIRECTORY_DESCRIPTOR_FILE);
        if (!descriptorFile.exists()) {
          continue;
        }

        // If subtree is included, count the number of entries for each
        // backup directory.
        if (subtree) {
          try {
            BackupDirectory backupDirectory =
                BackupDirectory.readBackupDirectoryDescriptor(f.getPath());
            count += backupDirectory.getBackups().keySet().size();
          } catch (Exception e) {
            return -1;
          }
        }

        count++;
      }
      return count;
    }

    // See if the requested entry was one level below the backend base entry.
    // If so, then it must point to a backup directory.  Otherwise, it must be
    // two levels below the backup base entry and must point to a specific
    // backup.
    DN parentDN = entryDN.getParentDNInSuffix();
    if (parentDN == null) {
      return -1;
    } else if (backupBaseDN.equals(parentDN)) {
      long count = 0;
      Entry backupDirEntry = getBackupDirectoryEntry(entryDN);

      AttributeType t = DirectoryServer.getAttributeType(ATTR_BACKUP_DIRECTORY_PATH, true);
      List<Attribute> attrList = backupDirEntry.getAttribute(t);
      if (attrList != null && !attrList.isEmpty()) {
        for (AttributeValue v : attrList.get(0)) {
          try {
            BackupDirectory backupDirectory =
                BackupDirectory.readBackupDirectoryDescriptor(v.getValue().toString());
            count += backupDirectory.getBackups().keySet().size();
          } catch (Exception e) {
            return -1;
          }
        }
      }
      return count;
    } else if (backupBaseDN.equals(parentDN.getParentDNInSuffix())) {
      return 0;
    } else {
      return -1;
    }
  }