From 2e56b3f76709f8f82fabad8a51362c18cbba5fe4 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 22 Sep 2014 08:46:59 +0000
Subject: [PATCH] OPENDJ-1206 (CR-4368) Create a new ReplicationBackend/ChangelogBackend to support cn=changelog

---
 opendj3-server-dev/src/server/org/opends/server/crypto/CryptoManagerSync.java |  283 ++++++++++++++++++++++++++------------------------------
 1 files changed, 130 insertions(+), 153 deletions(-)

diff --git a/opendj3-server-dev/src/server/org/opends/server/crypto/CryptoManagerSync.java b/opendj3-server-dev/src/server/org/opends/server/crypto/CryptoManagerSync.java
index 6bc9cf7..13648db 100644
--- a/opendj3-server-dev/src/server/org/opends/server/crypto/CryptoManagerSync.java
+++ b/opendj3-server-dev/src/server/org/opends/server/crypto/CryptoManagerSync.java
@@ -26,14 +26,23 @@
  */
 package org.opends.server.crypto;
 
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.DereferenceAliasesPolicy;
+import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
 import org.opends.admin.ads.ADSContext;
 import org.opends.server.api.Backend;
 import org.opends.server.api.BackendInitializationListener;
-import org.opends.server.api.ChangeNotificationListener;
+import org.opends.server.api.plugin.InternalDirectoryServerPlugin;
+import org.opends.server.api.plugin.PluginResult.PostResponse;
 import org.opends.server.config.ConfigConstants;
 import org.opends.server.controls.EntryChangeNotificationControl;
 import org.opends.server.controls.PersistentSearchChangeType;
@@ -43,71 +52,75 @@
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.ldap.LDAPControl;
-import org.opends.server.types.*;
-import org.forgerock.opendj.ldap.ResultCode;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.Control;
+import org.opends.server.types.CryptoManagerException;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.RDN;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchResultEntry;
 import org.opends.server.types.operation.PostResponseAddOperation;
 import org.opends.server.types.operation.PostResponseDeleteOperation;
 import org.opends.server.types.operation.PostResponseModifyOperation;
-import org.opends.server.types.operation.PostResponseModifyDNOperation;
 
 import static org.opends.messages.CoreMessages.*;
+import static org.opends.server.api.plugin.PluginType.*;
 import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.protocols.internal.InternalClientConnection.*;
 import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
 
-import java.util.LinkedHashSet;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.HashMap;
-
 /**
  * This class defines an object that synchronizes certificates from the admin
  * data branch into the trust store backend, and synchronizes secret-key entries
  * from the admin data branch to the crypto manager secret-key cache.
  */
-public class CryptoManagerSync
-     implements BackendInitializationListener, ChangeNotificationListener
+public class CryptoManagerSync extends InternalDirectoryServerPlugin
+     implements BackendInitializationListener
 {
-  /**
-   * The debug log tracer for this object.
-   */
+  /** The debug log tracer for this object. */
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
-
-
-  // The DN of the administration suffix.
+  /** The DN of the administration suffix. */
   private DN adminSuffixDN;
 
-  // The DN of the instance keys container within the admin suffix.
+  /** The DN of the instance keys container within the admin suffix. */
   private DN instanceKeysDN;
 
-  // The DN of the secret keys container within the admin suffix.
+  /** The DN of the secret keys container within the admin suffix. */
   private DN secretKeysDN;
 
-  // The DN of the trust store root.
+  /** The DN of the trust store root. */
   private DN trustStoreRootDN;
 
-  // The attribute type that is used to specify a server instance certificate.
-  AttributeType attrCert;
+  /** The attribute type that is used to specify a server instance certificate. */
+  private final AttributeType attrCert;
 
-  // The attribute type that holds a server certificate identifier.
-  AttributeType attrAlias;
+  /** The attribute type that holds a server certificate identifier. */
+  private final AttributeType attrAlias;
 
-  // The attribute type that holds the time a key was compromised.
-  AttributeType attrCompromisedTime;
+  /** The attribute type that holds the time a key was compromised. */
+  private final AttributeType attrCompromisedTime;
 
-  // A filter on object class to select key entries.
+  /** A filter on object class to select key entries. */
   private SearchFilter keySearchFilter;
 
-  // The instance key objectclass.
-  private ObjectClass ocInstanceKey;
+  /** The instance key objectclass. */
+  private final ObjectClass ocInstanceKey;
 
-  // The cipher key objectclass.
-  private ObjectClass ocCipherKey;
+  /** The cipher key objectclass. */
+  private final ObjectClass ocCipherKey;
 
-  // The mac key objectclass.
-  private ObjectClass ocMacKey;
+  /** The mac key objectclass. */
+  private final ObjectClass ocMacKey;
+
+  /** Dummy configuration DN. */
+  private static final String CONFIG_DN = "cn=Crypto Manager Sync,cn=config";
 
   /**
    * Creates a new instance of this trust store synchronization thread.
@@ -116,29 +129,17 @@
    * initialization, such as a failure to publish the instance-key-pair
    * public-key-certificate in ADS.
    */
-  public CryptoManagerSync()
-          throws InitializationException
+  public CryptoManagerSync() throws InitializationException
   {
-    this(true);
-  }
-
-  /**
-   * Creates a new instance of this trust store synchronization thread.
-   *
-   * @param publishInstanceKey whether the instance key must be published in
-   * the ADS or not.
-   * @throws InitializationException in case an exception occurs during
-   * initialization, such as a failure to publish the instance-key-pair
-   * public-key-certificate in ADS.
-   */
-  public CryptoManagerSync(boolean publishInstanceKey)
-  throws InitializationException
-  {
+    super(toDN(CONFIG_DN), EnumSet.of(
+        // No implementation required for modify_dn operations
+        // FIXME: Technically it is possible to perform a subtree modDN
+        // in this case however such subtree modDN would essentially be
+        // moving configuration branches which should not happen.
+        POST_RESPONSE_ADD, POST_RESPONSE_MODIFY, POST_RESPONSE_DELETE),
+        true);
     try {
-      if (publishInstanceKey)
-      {
-        CryptoManagerImpl.publishInstanceKeyEntryInADS();
-      }
+      CryptoManagerImpl.publishInstanceKeyEntryInADS();
     }
     catch (CryptoManagerException ex) {
       throw new InitializationException(ex.getMessageObject());
@@ -160,15 +161,11 @@
     }
     catch (DirectoryException e)
     {
-      //
     }
 
-    ocInstanceKey = DirectoryServer.getObjectClass(
-         OC_CRYPTO_INSTANCE_KEY, true);
-    ocCipherKey = DirectoryServer.getObjectClass(
-         OC_CRYPTO_CIPHER_KEY, true);
-    ocMacKey = DirectoryServer.getObjectClass(
-         OC_CRYPTO_MAC_KEY, true);
+    ocInstanceKey = DirectoryServer.getObjectClass(OC_CRYPTO_INSTANCE_KEY, true);
+    ocCipherKey = DirectoryServer.getObjectClass(OC_CRYPTO_CIPHER_KEY, true);
+    ocMacKey = DirectoryServer.getObjectClass(OC_CRYPTO_MAC_KEY, true);
 
     attrCert = DirectoryServer.getAttributeType(
          ConfigConstants.ATTR_CRYPTO_PUBLIC_KEY_CERTIFICATE, true);
@@ -182,22 +179,32 @@
       searchAdminSuffix();
     }
 
-    DirectoryServer.registerChangeNotificationListener(this);
+    DirectoryServer.registerInternalPlugin(this);
+  }
+
+  private static DN toDN(final String dn) throws InitializationException
+  {
+    try
+    {
+      return DN.valueOf(dn);
+    }
+    catch (DirectoryException e)
+    {
+      throw new RuntimeException(e);
+    }
   }
 
 
   private void searchAdminSuffix()
   {
-    InternalClientConnection conn =
-         InternalClientConnection.getRootConnection();
     LinkedHashSet<String> attributes = new LinkedHashSet<String>(0);
 
     ArrayList<Control> controls = new ArrayList<Control>(0);
 
     InternalSearchOperation searchOperation =
-         new InternalSearchOperation(conn,
-                                     InternalClientConnection.nextOperationID(),
-                                     InternalClientConnection.nextMessageID(),
+         new InternalSearchOperation(getRootConnection(),
+                                     nextOperationID(),
+                                     nextMessageID(),
                                      controls,
                                      adminSuffixDN, SearchScope.WHOLE_SUBTREE,
                                      DereferenceAliasesPolicy.NEVER,
@@ -231,9 +238,7 @@
   }
 
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public void performBackendInitializationProcessing(Backend backend)
   {
@@ -250,9 +255,7 @@
     }
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public void performBackendFinalizationProcessing(Backend backend)
   {
@@ -306,7 +309,7 @@
       {
         for (Control c : controls)
         {
-          if (c.getOID().equals(OID_ENTRY_CHANGE_NOTIFICATION))
+          if (OID_ENTRY_CHANGE_NOTIFICATION.equals(c.getOID()))
           {
             if (c instanceof LDAPControl)
             {
@@ -331,8 +334,7 @@
       if (ecn != null &&
            ecn.getChangeType() == PersistentSearchChangeType.DELETE)
       {
-        // The entry was deleted so we should remove it from the local trust
-        // store.
+        // entry was deleted so remove it from the local trust store
         if (dstEntry != null)
         {
           deleteEntry(dstDN);
@@ -340,24 +342,21 @@
       }
       else if (searchEntry.hasAttribute(attrCompromisedTime))
       {
-        // The key was compromised so we should remove it from the local
-        // trust store.
+        // key was compromised so remove it from the local trust store
         if (dstEntry != null)
         {
           deleteEntry(dstDN);
         }
       }
+      else if (dstEntry == null)
+      {
+        // The entry was added
+        addEntry(searchEntry, dstDN);
+      }
       else
       {
-        // The entry was added or modified.
-        if (dstEntry == null)
-        {
-          addEntry(searchEntry, dstDN);
-        }
-        else
-        {
-          modifyEntry(searchEntry, dstEntry);
-        }
+        // The entry was modified
+        modifyEntry(searchEntry, dstEntry);
       }
     }
   }
@@ -371,11 +370,8 @@
    */
   private void modifyEntry(Entry srcEntry, Entry dstEntry)
   {
-    List<Attribute> srcList;
-    srcList = srcEntry.getAttribute(attrCert);
-
-    List<Attribute> dstList;
-    dstList = dstEntry.getAttribute(attrCert);
+    List<Attribute> srcList = srcEntry.getAttribute(attrCert);
+    List<Attribute> dstList = dstEntry.getAttribute(attrCert);
 
     // Check for changes to the certificate value.
     boolean differ = false;
@@ -386,21 +382,12 @@
         differ = true;
       }
     }
-    else if (dstList == null)
+    else if (dstList == null
+        || srcList.size() != dstList.size()
+        || !srcList.equals(dstList))
     {
       differ = true;
     }
-    else if (srcList.size() != dstList.size())
-    {
-      differ = true;
-    }
-    else
-    {
-      if (!srcList.equals(dstList))
-      {
-        differ = true;
-      }
-    }
 
     if (differ)
     {
@@ -470,19 +457,22 @@
     }
   }
 
-
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
-  public void handleAddOperation(PostResponseAddOperation addOperation,
-                                 Entry entry)
+  public PostResponse doPostResponse(PostResponseAddOperation op)
   {
-    if (addOperation.getEntryDN().isDescendantOf(instanceKeysDN))
+    if (op.getResultCode() != ResultCode.SUCCESS)
+    {
+      return PostResponse.continueOperationProcessing();
+    }
+
+    final Entry entry = op.getEntryToAdd();
+    final DN entryDN = op.getEntryDN();
+    if (entryDN.isDescendantOf(instanceKeysDN))
     {
       handleInstanceKeyAddOperation(entry);
     }
-    else if (addOperation.getEntryDN().isDescendantOf(secretKeysDN))
+    else if (entryDN.isDescendantOf(secretKeysDN))
     {
       try
       {
@@ -501,6 +491,7 @@
             "Failed to import key entry: %s", e.getMessage()));
       }
     }
+    return PostResponse.continueOperationProcessing();
   }
 
 
@@ -521,19 +512,17 @@
     }
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
-  public void handleDeleteOperation(PostResponseDeleteOperation deleteOperation,
-                                    Entry entry)
+  public PostResponse doPostResponse(PostResponseDeleteOperation op)
   {
-    if (!deleteOperation.getEntryDN().isDescendantOf(instanceKeysDN))
+    if (op.getResultCode() != ResultCode.SUCCESS
+        || !op.getEntryDN().isDescendantOf(instanceKeysDN))
     {
-      return;
+      return PostResponse.continueOperationProcessing();
     }
 
-    RDN srcRDN = entry.getName().rdn();
+    RDN srcRDN = op.getEntryToDelete().getName().rdn();
 
     // Only process the entry if it has the expected form of RDN.
     // FIXME: Technically it is possible to perform a subtree in
@@ -542,24 +531,28 @@
     if (!srcRDN.isMultiValued() &&
          srcRDN.getAttributeType(0).equals(attrAlias))
     {
-      DN dstDN = trustStoreRootDN.child(srcRDN);
-
-      deleteEntry(dstDN);
+      DN destDN = trustStoreRootDN.child(srcRDN);
+      deleteEntry(destDN);
     }
+    return PostResponse.continueOperationProcessing();
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
-  public void handleModifyOperation(PostResponseModifyOperation modifyOperation,
-                                    Entry oldEntry, Entry newEntry)
+  public PostResponse doPostResponse(PostResponseModifyOperation op)
   {
-    if (modifyOperation.getEntryDN().isDescendantOf(instanceKeysDN))
+    if (op.getResultCode() != ResultCode.SUCCESS)
+    {
+      return PostResponse.continueOperationProcessing();
+    }
+
+    final Entry newEntry = op.getModifiedEntry();
+    final DN entryDN = op.getEntryDN();
+    if (entryDN.isDescendantOf(instanceKeysDN))
     {
       handleInstanceKeyModifyOperation(newEntry);
     }
-    else if (modifyOperation.getEntryDN().isDescendantOf(secretKeysDN))
+    else if (entryDN.isDescendantOf(secretKeysDN))
     {
       try
       {
@@ -578,6 +571,7 @@
             "Failed to import modified key entry: %s", e.getMessage()));
       }
     }
+    return PostResponse.continueOperationProcessing();
   }
 
   private void handleInstanceKeyModifyOperation(Entry newEntry)
@@ -610,31 +604,14 @@
           deleteEntry(dstDN);
         }
       }
+      else if (dstEntry == null)
+      {
+        addEntry(newEntry, dstDN);
+      }
       else
       {
-        if (dstEntry == null)
-        {
-          addEntry(newEntry, dstDN);
-        }
-        else
-        {
-          modifyEntry(newEntry, dstEntry);
-        }
+        modifyEntry(newEntry, dstEntry);
       }
     }
   }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public void handleModifyDNOperation(
-       PostResponseModifyDNOperation modifyDNOperation, Entry oldEntry,
-       Entry newEntry)
-  {
-    // No implementation required.
-    // FIXME: Technically it is possible to perform a subtree modDN
-    // in this case however such subtree modDN would essentially be
-    // moving configuration branches which should not happen.
-  }
 }

--
Gitblit v1.10.0