From e5e8ceb274a2795ec70cf8cc771a247e2620a30f Mon Sep 17 00:00:00 2001
From: jarnou <jarnou@localhost>
Date: Tue, 03 Jul 2007 09:29:17 +0000
Subject: [PATCH] Commits the refactoring of the core server to provide support for proxy/distribution/virtual functionnalities. This includes the new set of local operations, as well as the workflow and networkgroup support.
---
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java | 3
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java | 41
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/NetworkGroupTest.java | 470 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java | 21
opendj-sdk/opends/src/server/org/opends/server/api/SynchronizationProvider.java | 30
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CharacterSetPasswordValidatorTestCase.java | 11
opendj-sdk/opends/src/server/org/opends/server/core/WorkflowImpl.java | 127
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java | 27
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java | 4
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UniqueCharactersPasswordValidatorTestCase.java | 36
opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroup.java | 407
opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java | 83
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java | 10
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AbandonOperationTestCase.java | 20
opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupNamingContexts.java | 157
opendj-sdk/opends/src/server/org/opends/server/core/AddOperationWrapper.java | 653 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentServerStateTest.java | 5
opendj-sdk/opends/src/server/org/opends/server/core/BindOperationBasis.java | 959 ++
opendj-sdk/opends/src/server/org/opends/server/core/ExtendedOperation.java | 79
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java | 7
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RepeatedCharactersPasswordValidatorTestCase.java | 34
opendj-sdk/opends/src/server/org/opends/server/core/DefaultAccessControlProvider.java | 18
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java | 7
opendj-sdk/opends/src/server/org/opends/server/core/PersistentSearch.java | 12
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentStateTest.java | 5
opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperationBasis.java | 671 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SimilarityBasedPasswordValidatorTestCase.java | 10
opendj-sdk/opends/src/server/org/opends/server/core/AbandonOperation.java | 86
opendj-sdk/opends/src/server/org/opends/server/core/BindOperation.java | 2244 ----
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java | 3
opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java | 2933 ------
opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupCriteria.java | 46
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java | 23
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java | 19
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java | 14
opendj-sdk/opends/src/server/org/opends/server/core/WorkflowTopologyNode.java | 535 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java | 938 ++
opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationWrapper.java | 903 ++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LengthBasedPasswordValidatorTestCase.java | 18
opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java | 19
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java | 25
opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperationWrapper.java | 622 +
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java | 4
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DictionaryPasswordValidatorTestCase.java | 13
opendj-sdk/opends/src/server/org/opends/server/api/AccessControlHandler.java | 30
opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java | 30
opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java | 35
opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java | 126
opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java | 4
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxTestCase.java | 4
opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java | 81
opendj-sdk/opends/src/server/org/opends/server/types/Operation.java | 553 -
opendj-sdk/opends/src/server/org/opends/server/workflowelement/LeafWorkflowElement.java | 40
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/StressTest.java | 6
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java | 41
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java | 12
opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperationWrapper.java | 569 +
opendj-sdk/opends/src/server/org/opends/server/core/PluginConfigManager.java | 228
opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java | 1385 ---
opendj-sdk/opends/src/server/org/opends/server/types/AbstractOperation.java | 691 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java | 62
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProviderTestCase.java | 6
opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkerThread.java | 9
opendj-sdk/opends/src/server/org/opends/server/core/WorkflowResultCode.java | 249
opendj-sdk/opends/src/server/org/opends/server/core/Workflow.java | 73
opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java | 6
opendj-sdk/opends/src/server/org/opends/server/core/UnbindOperation.java | 68
opendj-sdk/opends/src/server/org/opends/server/core/RootDseWorkflowTopology.java | 175
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ServerSideSortControlTestCase.java | 30
opendj-sdk/opends/src/server/org/opends/server/core/BindOperationWrapper.java | 691 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java | 4
opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java | 10
opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationBasis.java | 1759 +++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ModifyConflictTest.java | 7
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AttributeValuePasswordValidatorTestCase.java | 10
opendj-sdk/opends/src/server/org/opends/server/core/AddOperationBasis.java | 1024 ++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/VLVControlTestCase.java | 36
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/SchemaReplicationTest.java | 5
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AnonymousSASLMechanismHandlerTestCase.java | 14
opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java | 87
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReSyncTest.java | 8
opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupPolicy.java | 46
opendj-sdk/opends/src/server/org/opends/server/config/JMXMBean.java | 4
opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperationBasis.java | 773 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java | 64
opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalSearchOperation.java | 25
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java | 62
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/UpdateComparatorTest.java | 3
opendj-sdk/opends/src/server/org/opends/server/loggers/TextAuditLogPublisher.java | 19
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java | 130
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java | 87
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java | 5
opendj-sdk/opends/src/server/org/opends/server/core/WorkflowTopology.java | 135
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java | 5
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java | 28
opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkQueue.java | 35
opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java | 19
opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java | 2516 -----
opendj-sdk/opends/src/server/org/opends/server/workflowelement/WorkflowElement.java | 81
opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java | 107
opendj-sdk/opends/src/server/org/opends/server/api/WorkQueue.java | 4
opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java | 3
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxConnectTest.java | 9
opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java | 2310 ----
104 files changed, 14,465 insertions(+), 12,525 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/AccessControlHandler.java b/opendj-sdk/opends/src/server/org/opends/server/api/AccessControlHandler.java
index 0639d14..be102f9 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/AccessControlHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/AccessControlHandler.java
@@ -27,9 +27,9 @@
package org.opends.server.api;
-
import org.opends.server.core.*;
import org.opends.server.types.*;
+import org.opends.server.workflowelement.localbackend.*;
/**
@@ -53,7 +53,8 @@
* the access control configuration, or <CODE>false</CODE>
* if not.
*/
- public abstract boolean isAllowed(AddOperation addOperation);
+ public abstract boolean isAllowed(LocalBackendAddOperation
+ addOperation);
@@ -69,7 +70,8 @@
* the access control configuration, or <CODE>false</CODE>
* if not.
*/
- public abstract boolean isAllowed(BindOperation bindOperation);
+ public abstract boolean isAllowed(LocalBackendBindOperation
+ bindOperation);
@@ -102,7 +104,8 @@
* the access control configuration, or <CODE>false</CODE>
* if not.
*/
- public abstract boolean isAllowed(DeleteOperation deleteOperation);
+ public abstract boolean isAllowed(LocalBackendDeleteOperation
+ deleteOperation);
@@ -135,7 +138,8 @@
* the access control configuration, or <CODE>false</CODE>
* if not.
*/
- public abstract boolean isAllowed(ModifyOperation modifyOperation);
+ public abstract boolean isAllowed(LocalBackendModifyOperation
+ modifyOperation);
@@ -171,7 +175,8 @@
* the access control configuration, or <CODE>false</CODE>
* if not.
*/
- public abstract boolean isAllowed(SearchOperation searchOperation);
+ public abstract boolean isAllowed(LocalBackendSearchOperation
+ searchOperation);
@@ -189,8 +194,9 @@
* the access control configuration, or <CODE>false</CODE>
* if not.
*/
- public abstract boolean maySend(SearchOperation searchOperation,
- SearchResultEntry searchEntry);
+ public abstract boolean maySend(
+ SearchOperation searchOperation,
+ SearchResultEntry searchEntry);
@@ -207,7 +213,8 @@
* removed.
*/
public abstract SearchResultEntry filterEntry(
- SearchOperation searchOperation, SearchResultEntry searchEntry);
+ SearchOperation searchOperation,
+ SearchResultEntry searchEntry);
@@ -225,8 +232,9 @@
* the access control configuration, or <CODE>false</CODE>
* if not.
*/
- public abstract boolean maySend(SearchOperation searchOperation,
- SearchResultReference searchReference);
+ public abstract boolean maySend(
+ SearchOperation searchOperation,
+ SearchResultReference searchReference);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java b/opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java
index 46475d5..cacc625 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java
@@ -41,6 +41,8 @@
import org.opends.server.core.PersistentSearch;
import org.opends.server.core.PluginConfigManager;
import org.opends.server.core.SearchOperation;
+import org.opends.server.core.NetworkGroup;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
@@ -117,6 +119,9 @@
// A set of persistent searches registered for this client.
private CopyOnWriteArrayList<PersistentSearch> persistentSearches;
+ // The network group to which the connection belongs to.
+ private NetworkGroup networkGroup;
+
/**
@@ -136,6 +141,7 @@
lookthroughLimit = DirectoryServer.getLookthroughLimit();
finalized = false;
privileges = new HashSet<Privilege>();
+ networkGroup = NetworkGroup.getDefaultNetworkGroup();
}
@@ -653,7 +659,8 @@
* @return The set of operations in progress for this client
* connection.
*/
- public abstract Collection<Operation> getOperationsInProgress();
+ public abstract Collection<AbstractOperation>
+ getOperationsInProgress();
@@ -667,7 +674,8 @@
* or <CODE>null</CODE> if no such operation could be
* found.
*/
- public abstract Operation getOperationInProgress(int messageID);
+ public abstract AbstractOperation
+ getOperationInProgress(int messageID);
@@ -1542,5 +1550,28 @@
{
finalizeConnectionInternal();
}
+
+
+ /**
+ * Returns the network group to which the connection belongs.
+ *
+ * @return the network group attached to the connection
+ */
+ public NetworkGroup getNetworkGroup()
+ {
+ return networkGroup;
+ }
+
+ /**
+ * Sets the network group to which the connection belongs.
+ *
+ * @param networkGroup the network group to which the
+ * connections belongs to
+ */
+ public void setNetworkGroup (NetworkGroup networkGroup)
+ {
+ this.networkGroup = networkGroup;
+ }
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/SynchronizationProvider.java b/opendj-sdk/opends/src/server/org/opends/server/api/SynchronizationProvider.java
index 2fb1657..01bb2a1 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/SynchronizationProvider.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/SynchronizationProvider.java
@@ -32,14 +32,12 @@
import org.opends.server.admin.std.server.SynchronizationProviderCfg;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.DeleteOperation;
-import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Modification;
import org.opends.server.types.SynchronizationProviderResult;
+import org.opends.server.workflowelement.localbackend.*;
@@ -109,7 +107,8 @@
* synchronization processing.
*/
public SynchronizationProviderResult
- handleConflictResolution(AddOperation addOperation)
+ handleConflictResolution(LocalBackendAddOperation
+ addOperation)
throws DirectoryException
{
// No processing is required by default.
@@ -136,7 +135,8 @@
* synchronization processing.
*/
public abstract SynchronizationProviderResult
- doPreOperation(AddOperation addOperation)
+ doPreOperation(LocalBackendAddOperation
+ addOperation)
throws DirectoryException;
@@ -153,7 +153,8 @@
* @throws DirectoryException If a problem occurs during
* synchronization processing.
*/
- public abstract void doPostOperation(AddOperation addOperation)
+ public abstract void doPostOperation(LocalBackendAddOperation
+ addOperation)
throws DirectoryException;
@@ -177,7 +178,8 @@
* synchronization processing.
*/
public SynchronizationProviderResult
- handleConflictResolution(DeleteOperation deleteOperation)
+ handleConflictResolution(LocalBackendDeleteOperation
+ deleteOperation)
throws DirectoryException
{
// No processing is required by default.
@@ -204,7 +206,8 @@
* synchronization processing.
*/
public abstract SynchronizationProviderResult
- doPreOperation(DeleteOperation deleteOperation)
+ doPreOperation(LocalBackendDeleteOperation
+ deleteOperation)
throws DirectoryException;
@@ -222,7 +225,8 @@
* synchronization processing.
*/
public abstract void doPostOperation(
- DeleteOperation deleteOperation)
+ LocalBackendDeleteOperation
+ deleteOperation)
throws DirectoryException;
@@ -246,7 +250,7 @@
* synchronization processing.
*/
public SynchronizationProviderResult
- handleConflictResolution(ModifyOperation
+ handleConflictResolution(LocalBackendModifyOperation
modifyOperation)
throws DirectoryException
{
@@ -274,7 +278,8 @@
* synchronization processing.
*/
public abstract SynchronizationProviderResult
- doPreOperation(ModifyOperation modifyOperation)
+ doPreOperation(LocalBackendModifyOperation
+ modifyOperation)
throws DirectoryException;
@@ -292,7 +297,8 @@
* synchronization processing.
*/
public abstract void doPostOperation(
- ModifyOperation modifyOperation)
+ LocalBackendModifyOperation
+ modifyOperation)
throws DirectoryException;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/WorkQueue.java b/opendj-sdk/opends/src/server/org/opends/server/api/WorkQueue.java
index 55b61d2..7375b5c 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/WorkQueue.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/WorkQueue.java
@@ -30,9 +30,9 @@
import org.opends.server.admin.std.server.WorkQueueCfg;
import org.opends.server.config.ConfigException;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.InitializationException;
-import org.opends.server.types.Operation;
@@ -95,7 +95,7 @@
* already has too many pending
* requests in the queue).
*/
- public abstract void submitOperation(Operation operation)
+ public abstract void submitOperation(AbstractOperation operation)
throws DirectoryException;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
index c2126da..06e9a8f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciContainer.java
@@ -30,8 +30,8 @@
import org.opends.server.types.*;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.Group;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.api.ConnectionSecurityProvider;
-import org.opends.server.core.AddOperation;
import org.opends.server.core.SearchOperation;
import org.opends.server.extensions.TLSConnectionSecurityProvider;
import org.opends.server.types.Operation;
@@ -250,7 +250,7 @@
this.resourceEntry=entry;
this.operation=operation;
this.clientConnection=operation.getClientConnection();
- if(operation instanceof AddOperation)
+ if(operation instanceof AddOperationBasis)
this.isAddOp=true;
//If the proxied authorization control was processed, then the operation
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
index e934089..ab0ad50 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -27,11 +27,14 @@
package org.opends.server.authorization.dseecompat;
+
+import static org.opends.server.authorization.dseecompat.Aci.*;
+
import org.opends.server.admin.std.server.DseeCompatAccessControlHandlerCfg;
import org.opends.server.api.AccessControlHandler;
-import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.config.ConfigConstants.ATTR_AUTHZ_GLOBAL_ACI;
import org.opends.server.core.*;
+
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
@@ -49,6 +52,8 @@
import java.util.*;
import java.util.concurrent.locks.Lock;
+import org.opends.server.workflowelement.localbackend.*;
+
/**
* The AciHandler class performs the main processing for the
* dseecompat package.
@@ -259,7 +264,7 @@
* @return True if access is allowed.
*/
private boolean aciCheckMods(AciLDAPOperationContainer container,
- ModifyOperation operation,
+ LocalBackendModifyOperation operation,
boolean skipAccessCheck) {
Entry resourceEntry=container.getResourceEntry();
DN dn=resourceEntry.getDN();
@@ -833,7 +838,7 @@
* @param operation The add operation to check access on.
* @return True if access is allowed.
*/
- public boolean isAllowed(AddOperation operation) {
+ public boolean isAllowed(LocalBackendAddOperation operation) {
AciLDAPOperationContainer operationContainer =
new AciLDAPOperationContainer(operation, ACI_ADD);
boolean ret=isAllowed(operationContainer,operation);
@@ -883,7 +888,7 @@
* @param operation The delete operation to check access on.
* @return True if access is allowed.
*/
- public boolean isAllowed(DeleteOperation operation) {
+ public boolean isAllowed(LocalBackendDeleteOperation operation) {
AciLDAPOperationContainer operationContainer=
new AciLDAPOperationContainer(operation, ACI_DELETE);
return isAllowed(operationContainer, operation);
@@ -896,7 +901,7 @@
* @return True if access is allowed.
*/
- public boolean isAllowed(ModifyOperation operation) {
+ public boolean isAllowed(LocalBackendModifyOperation operation) {
AciLDAPOperationContainer operationContainer=
new AciLDAPOperationContainer(operation, ACI_NULL);
return aciCheckMods(operationContainer, operation,
@@ -1169,7 +1174,7 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(BindOperation bindOperation) {
+ public boolean isAllowed(LocalBackendBindOperation bindOperation) {
//Not planned to be implemented.
return true;
}
@@ -1187,7 +1192,7 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(SearchOperation searchOperation) {
+ public boolean isAllowed(LocalBackendSearchOperation searchOperation) {
//Not planned to be implemented.
return true;
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
index cf1898d..2f791e4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciLDAPOperationContainer.java
@@ -33,6 +33,7 @@
import org.opends.server.types.Modification;
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.Entry;
+import org.opends.server.workflowelement.localbackend.*;
/**
* The AciLDAPOperationContainer is an AciContainer
@@ -66,7 +67,9 @@
* @param operation The add operation to evaluate.
* @param rights The rights of an add operation.
*/
- public AciLDAPOperationContainer(AddOperation operation, int rights) {
+ public AciLDAPOperationContainer(LocalBackendAddOperation operation,
+ int rights)
+ {
super(operation, rights, operation.getEntryToAdd());
}
@@ -75,7 +78,9 @@
* @param operation The add operation to evaluate.
* @param rights The rights of a delete operation.
*/
- public AciLDAPOperationContainer(DeleteOperation operation, int rights) {
+ public AciLDAPOperationContainer(LocalBackendDeleteOperation operation,
+ int rights)
+ {
super(operation, rights, operation.getEntryToDelete());
}
@@ -84,7 +89,9 @@
* @param rights The rights of modify operation.
* @param operation The add operation to evaluate.
*/
- public AciLDAPOperationContainer(ModifyOperation operation, int rights) {
+ public AciLDAPOperationContainer(LocalBackendModifyOperation operation,
+ int rights)
+ {
super(operation, rights, operation.getCurrentEntry());
this.modifications=operation.getModifications();
}
@@ -106,8 +113,10 @@
* @param rights The rights of a search operation.
* @param entry The entry to be evaluated for this search.
*/
- public AciLDAPOperationContainer(SearchOperation operation, int rights,
- SearchResultEntry entry) {
+ public AciLDAPOperationContainer(SearchOperation operation,
+ int rights,
+ SearchResultEntry entry)
+ {
super(operation, rights, entry);
this.searchEntry = entry;
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java
index 4e1e10b..5cc1340 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/authorization/dseecompat/AciListenerManager.java
@@ -27,6 +27,7 @@
package org.opends.server.authorization.dseecompat;
+import org.opends.server.workflowelement.localbackend.*;
import org.opends.server.api.ChangeNotificationListener;
import org.opends.server.api.BackendInitializationListener;
import org.opends.server.api.Backend;
@@ -235,8 +236,10 @@
null, baseDN, SearchScope.WHOLE_SUBTREE,
DereferencePolicy.NEVER_DEREF_ALIASES,
0, 0, false, aciFilter, attrs, null);
+ LocalBackendSearchOperation localInternalSearch =
+ new LocalBackendSearchOperation(internalSearch);
try {
- backend.search(internalSearch);
+ backend.search(localInternalSearch);
} catch (Exception e) {
if (debugEnabled())
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/config/JMXMBean.java b/opendj-sdk/opends/src/server/org/opends/server/config/JMXMBean.java
index 25a8f44..1754572 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/config/JMXMBean.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/config/JMXMBean.java
@@ -82,7 +82,7 @@
import org.opends.server.protocols.ldap.LDAPModification;
import org.opends.server.protocols.ldap.LDAPAttribute ;
import org.opends.server.protocols.internal.InternalSearchOperation ;
-import org.opends.server.core.ModifyOperation ;
+import org.opends.server.core.ModifyOperationBasis ;
import org.opends.server.types.LDAPException;
import org.opends.server.types.ModificationType;
@@ -828,7 +828,7 @@
//
// Process the modify
- ModifyOperation op = jmxClientConnection.processModify(
+ ModifyOperationBasis op = jmxClientConnection.processModify(
new ASN1OctetString(configEntryDN.toString()),
ldapModList);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/AbandonOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/AbandonOperation.java
index fdcefa8..cf2d828 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/AbandonOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/AbandonOperation.java
@@ -28,26 +28,30 @@
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ERROR_MESSAGE;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ID_TO_ABANDON;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_PROCESSING_TIME;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_RESULT_CODE;
+import static org.opends.server.messages.CoreMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+
import java.util.List;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.plugin.PreParsePluginResult;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.Control;
import org.opends.server.types.DisconnectReason;
-import org.opends.server.types.Operation;
import org.opends.server.types.OperationType;
import org.opends.server.types.ResultCode;
import org.opends.server.types.operation.PostOperationAbandonOperation;
import org.opends.server.types.operation.PreParseAbandonOperation;
-import static org.opends.server.core.CoreConstants.*;
import static org.opends.server.loggers.AccessLogger.*;
-import static org.opends.server.messages.CoreMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-
-
/**
@@ -55,23 +59,18 @@
* may already be in progress in the Directory Server.
*/
public class AbandonOperation
- extends Operation
+ extends AbstractOperation
implements PreParseAbandonOperation, PostOperationAbandonOperation
{
-
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
// The message ID of the operation that should be abandoned.
private final int idToAbandon;
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
-
-
/**
* Creates a new abandon operation with the provided information.
*
@@ -106,41 +105,6 @@
return idToAbandon;
}
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
-
/**
* {@inheritDoc}
*/
@@ -213,7 +177,7 @@
}
String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
+ String.valueOf(getProcessingTime());
return new String[][]
{
@@ -261,9 +225,12 @@
/**
- * {@inheritDoc}
+ * Performs the work of actually processing this operation. This
+ * should include all processing for the operation, including
+ * invoking plugins, logging messages, performing access control,
+ * managing synchronization, and any other work that might need to
+ * be done in the course of processing.
*/
- @Override()
public final void run()
{
setResultCode(ResultCode.UNDEFINED);
@@ -276,7 +243,7 @@
// Start the processing timer.
- processingStartTime = System.currentTimeMillis();
+ setProcessingStartTime();
// Create a labeled block of code that we can break out of if a problem is
@@ -295,7 +262,7 @@
int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logAbandonRequest(this);
logAbandonResult(this);
@@ -321,7 +288,7 @@
// code to reflect whether the abandon was successful and an error message
// if it was not. Even though there is no response, the result should
// still be logged.
- Operation operation =
+ AbstractOperation operation =
clientConnection.getOperationInProgress(idToAbandon);
if (operation == null)
{
@@ -356,7 +323,7 @@
// Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
// Log the result of the abandon operation.
@@ -392,7 +359,7 @@
* {@inheritDoc}
*/
@Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
+ public boolean setCancelRequest(CancelRequest cancelRequest)
{
// Abandon operations cannot be canceled.
return false;
@@ -414,5 +381,6 @@
buffer.append(idToAbandon);
buffer.append(")");
}
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java
index 8b265d1..a81b672 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/AddOperation.java
@@ -26,248 +26,23 @@
*/
package org.opends.server.core;
-
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.locks.Lock;
-import org.opends.server.api.AttributeSyntax;
-import org.opends.server.api.Backend;
-import org.opends.server.api.ChangeNotificationListener;
-import org.opends.server.api.ClientConnection;
-import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.api.PasswordValidator;
-import org.opends.server.api.SynchronizationProvider;
-import org.opends.server.api.plugin.PostOperationPluginResult;
-import org.opends.server.api.plugin.PreOperationPluginResult;
-import org.opends.server.api.plugin.PreParsePluginResult;
-import org.opends.server.controls.LDAPAssertionRequestControl;
-import org.opends.server.controls.LDAPPostReadRequestControl;
-import org.opends.server.controls.LDAPPostReadResponseControl;
-import org.opends.server.controls.ProxiedAuthV1Control;
-import org.opends.server.controls.ProxiedAuthV2Control;
-import org.opends.server.schema.AuthPasswordSyntax;
-import org.opends.server.schema.BooleanSyntax;
-import org.opends.server.schema.UserPasswordSyntax;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.ldap.LDAPAttribute;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
import org.opends.server.types.ByteString;
-import org.opends.server.types.CancelledOperationException;
-import org.opends.server.types.CancelRequest;
-import org.opends.server.types.CancelResult;
-import org.opends.server.types.Control;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.LDAPException;
-import org.opends.server.types.LockManager;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Operation;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.Privilege;
import org.opends.server.types.RawAttribute;
-import org.opends.server.types.RDN;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SynchronizationProviderResult;
-import org.opends.server.types.operation.PostOperationAddOperation;
-import org.opends.server.types.operation.PostResponseAddOperation;
-import org.opends.server.types.operation.PreOperationAddOperation;
-import org.opends.server.types.operation.PreParseAddOperation;
-import org.opends.server.util.TimeThread;
-
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.core.CoreConstants.*;
-import static org.opends.server.loggers.AccessLogger.*;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-import static org.opends.server.messages.CoreMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
-
-
/**
- * This class defines an operation that may be used to add a new entry to the
- * Directory Server.
+ * This interface defines an operation that may be used to add a new entry to
+ * the Directory Server.
*/
-public class AddOperation
- extends Operation
- implements PreParseAddOperation, PreOperationAddOperation,
- PostOperationAddOperation, PostResponseAddOperation
+public interface AddOperation extends Operation
{
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- // The set of response controls to send to the client.
- private ArrayList<Control> responseControls;
-
- // The raw, unprocessed entry DN as provided in the request. This may or may
- // not be a valid DN.
- private ByteString rawEntryDN;
-
- // The cancel request that has been issued for this add operation.
- private CancelRequest cancelRequest;
-
- // The processed DN of the entry to add.
- private DN entryDN;
-
- // The proxied authorization target DN for this operation.
- private DN proxiedAuthorizationDN;
-
- // The entry being added to the server.
- private Entry entry;
-
- // The set of attributes (including the objectclass attribute) in a raw,
- // unprocessed form as provided in the request. One or more of these
- // attributes may be invalid.
- private List<RawAttribute> rawAttributes;
-
- // The set of operational attributes for the entry to add.
- private Map<AttributeType,List<Attribute>> operationalAttributes;
-
- // The set of user attributes for the entry to add.
- private Map<AttributeType,List<Attribute>> userAttributes;
-
- // The set of objectclasses for the entry to add.
- private Map<ObjectClass,String> objectClasses;
-
- // The change number that has been assigned to this operation.
- private long changeNumber;
-
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
-
-
- /**
- * Creates a new add operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param rawEntryDN The raw DN of the entry to add from the client
- * request. This may or may not be a valid DN.
- * @param rawAttributes The raw set of attributes from the client
- * request (including the objectclass attribute).
- * This may contain invalid attributes.
- */
- public AddOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- ByteString rawEntryDN, List<RawAttribute> rawAttributes)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.rawEntryDN = rawEntryDN;
- this.rawAttributes = rawAttributes;
-
- responseControls = new ArrayList<Control>();
- cancelRequest = null;
- entry = null;
- entryDN = null;
- userAttributes = null;
- operationalAttributes = null;
- objectClasses = null;
- proxiedAuthorizationDN = null;
- changeNumber = -1;
- }
-
-
-
- /**
- * Creates a new add operation with the provided information.
- *
- * @param clientConnection The client connection with which this
- * operation is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which
- * this operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param entryDN The DN for the entry.
- * @param objectClasses The set of objectclasses for the entry.
- * @param userAttributes The set of user attributes for the entry.
- * @param operationalAttributes The set of operational attributes for the
- * entry.
- */
- public AddOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- DN entryDN, Map<ObjectClass,String> objectClasses,
- Map<AttributeType,List<Attribute>> userAttributes,
- Map<AttributeType,List<Attribute>> operationalAttributes)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.entryDN = entryDN;
- this.objectClasses = objectClasses;
- this.userAttributes = userAttributes;
- this.operationalAttributes = operationalAttributes;
-
- entry = null;
-
- rawEntryDN = new ASN1OctetString(entryDN.toString());
-
- rawAttributes = new ArrayList<RawAttribute>();
-
- ArrayList<ASN1OctetString> ocValues = new ArrayList<ASN1OctetString>();
- for (String s : objectClasses.values())
- {
- ocValues.add(new ASN1OctetString(s));
- }
-
- LDAPAttribute ocAttr = new LDAPAttribute(ATTR_OBJECTCLASS, ocValues);
- rawAttributes.add(ocAttr);
-
- for (List<Attribute> attrList : userAttributes.values())
- {
- for (Attribute a : attrList)
- {
- rawAttributes.add(new LDAPAttribute(a));
- }
- }
-
- for (List<Attribute> attrList : operationalAttributes.values())
- {
- for (Attribute a : attrList)
- {
- rawAttributes.add(new LDAPAttribute(a));
- }
- }
-
- responseControls = new ArrayList<Control>();
- proxiedAuthorizationDN = null;
- cancelRequest = null;
- changeNumber = -1;
- }
-
-
/**
* Retrieves the DN of the entry to add in a raw, unparsed form as it was
@@ -276,12 +51,7 @@
*
* @return The DN of the entry in a raw, unparsed form.
*/
- public final ByteString getRawEntryDN()
- {
- return rawEntryDN;
- }
-
-
+ public abstract ByteString getRawEntryDN();
/**
* Specifies the raw entry DN for the entry to add. This should only be
@@ -292,14 +62,7 @@
*
* @param rawEntryDN The raw entry DN for the entry to add.
*/
- public final void setRawEntryDN(ByteString rawEntryDN)
- {
- this.rawEntryDN = rawEntryDN;
-
- entryDN = null;
- }
-
-
+ public abstract void setRawEntryDN(ByteString rawEntryDN);
/**
* Retrieves the DN of the entry to add. This method should not be called
@@ -309,12 +72,7 @@
* @return The DN of the entry to add, or <CODE>null</CODE> if it has not yet
* been parsed from the raw DN.
*/
- public final DN getEntryDN()
- {
- return entryDN;
- }
-
-
+ public abstract DN getEntryDN();
/**
* Retrieves the set of attributes in their raw, unparsed form as read from
@@ -325,12 +83,7 @@
* @return The set of attributes in their raw, unparsed form as read from the
* client request.
*/
- public final List<RawAttribute> getRawAttributes()
- {
- return rawAttributes;
- }
-
-
+ public abstract List<RawAttribute> getRawAttributes();
/**
* Adds the provided attribute to the set of raw attributes for this add
@@ -339,16 +92,7 @@
* @param rawAttribute The attribute to add to the set of raw attributes for
* this add operation.
*/
- public final void addRawAttribute(RawAttribute rawAttribute)
- {
- rawAttributes.add(rawAttribute);
-
- objectClasses = null;
- userAttributes = null;
- operationalAttributes = null;
- }
-
-
+ public abstract void addRawAttribute(RawAttribute rawAttribute);
/**
* Replaces the set of raw attributes for this add operation. This should
@@ -356,65 +100,7 @@
*
* @param rawAttributes The set of raw attributes for this add operation.
*/
- public final void setRawAttributes(List<RawAttribute> rawAttributes)
- {
- this.rawAttributes = rawAttributes;
-
- objectClasses = null;
- userAttributes = null;
- operationalAttributes = null;
- }
-
-
-
- /**
- * Retrieves the set of processed objectclasses for the entry to add. This
- * should not be called by pre-parse plugins because this information will not
- * yet be available. The contents of the returned map may not be altered by
- * the caller.
- *
- * @return The set of processed objectclasses for the entry to add, or
- * <CODE>null</CODE> if that information is not yet available.
- */
- public final Map<ObjectClass,String> getObjectClasses()
- {
- return objectClasses;
- }
-
-
-
- /**
- * Adds the provided objectclass to the entry to add. This should only be
- * called from pre-operation plugins. Note that pre-operation plugin
- * processing is invoked after access control and schema validation, so
- * plugins should be careful to only make changes that will not violate either
- * schema or access control rules.
- *
- * @param objectClass The objectclass to add to the entry.
- * @param name The name to use for the objectclass.
- */
- public final void addObjectClass(ObjectClass objectClass, String name)
- {
- objectClasses.put(objectClass, name);
- }
-
-
-
- /**
- * Removes the provided objectclass from the entry to add. This should only
- * be called from pre-operation plugins. Note that pre-operation plugin
- * processing is invoked after access control and schema validation, so
- * plugins should be careful to only make changes that will not violate either
- * schema or access control rules.
- *
- * @param objectClass The objectclass to remove from the entry.
- */
- public final void removeObjectClass(ObjectClass objectClass)
- {
- objectClasses.remove(objectClass);
- }
-
-
+ public abstract void setRawAttributes(List<RawAttribute> rawAttributes);
/**
* Retrieves the set of processed user attributes for the entry to add. This
@@ -425,28 +111,7 @@
* @return The set of processed user attributes for the entry to add, or
* <CODE>null</CODE> if that information is not yet available.
*/
- public final Map<AttributeType,List<Attribute>> getUserAttributes()
- {
- return userAttributes;
- }
-
-
-
- /**
- * Retrieves the set of processed operational attributes for the entry to add.
- * This should not be called by pre-parse plugins because this information
- * will not yet be available. The contents of the returned map may be altered
- * by the caller.
- *
- * @return The set of processed operational attributes for the entry to add,
- * or <CODE>null</CODE> if that information is not yet available.
- */
- public final Map<AttributeType,List<Attribute>> getOperationalAttributes()
- {
- return operationalAttributes;
- }
-
-
+ public abstract Map<AttributeType, List<Attribute>> getUserAttributes();
/**
* Sets the specified attribute in the entry to add, overwriting any existing
@@ -459,34 +124,8 @@
* @param attributeType The attribute type for the attribute.
* @param attributeList The attribute list for the provided attribute type.
*/
- public final void setAttribute(AttributeType attributeType,
- List<Attribute> attributeList)
- {
- if (attributeType.isOperational())
- {
- if ((attributeList == null) || (attributeList.isEmpty()))
- {
- operationalAttributes.remove(attributeType);
- }
- else
- {
- operationalAttributes.put(attributeType, attributeList);
- }
- }
- else
- {
- if ((attributeList == null) || (attributeList.isEmpty()))
- {
- userAttributes.remove(attributeType);
- }
- else
- {
- userAttributes.put(attributeType, attributeList);
- }
- }
- }
-
-
+ public abstract void setAttribute(AttributeType attributeType,
+ List<Attribute> attributeList);
/**
* Removes the specified attribute from the entry to add. This should only be
@@ -497,67 +136,7 @@
*
* @param attributeType The attribute tyep for the attribute to remove.
*/
- public final void removeAttribute(AttributeType attributeType)
- {
- if (attributeType.isOperational())
- {
- operationalAttributes.remove(attributeType);
- }
- else
- {
- userAttributes.remove(attributeType);
- }
- }
-
-
-
- /**
- * Retrieves the entry to be added to the server. Note that this will not be
- * available to pre-parse plugins or during the conflict resolution portion of
- * the synchronization processing.
- *
- * @return The entry to be added to the server, or <CODE>null</CODE> if it is
- * not yet available.
- */
- public final Entry getEntryToAdd()
- {
- return entry;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
+ public abstract void removeAttribute(AttributeType attributeType);
/**
* Retrieves the change number that has been assigned to this operation.
@@ -566,12 +145,7 @@
* if none has been assigned yet or if there is no applicable
* synchronization mechanism in place that uses change numbers.
*/
- public final long getChangeNumber()
- {
- return changeNumber;
- }
-
-
+ public abstract long getChangeNumber();
/**
* Specifies the change number that has been assigned to this operation by the
@@ -580,131 +154,52 @@
* @param changeNumber The change number that has been assigned to this
* operation by the synchronization mechanism.
*/
- public final void setChangeNumber(long changeNumber)
- {
- this.changeNumber = changeNumber;
- }
-
-
+ public abstract void setChangeNumber(long changeNumber);
/**
- * {@inheritDoc}
+ * Retrieves the set of processed objectclasses for the entry to add. This
+ * should not be called by pre-parse plugins because this information will not
+ * yet be available. The contents of the returned map may not be altered by
+ * the caller.
+ *
+ * @return The set of processed objectclasses for the entry to add, or
+ * <CODE>null</CODE> if that information is not yet available.
*/
- @Override()
- public final OperationType getOperationType()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- return OperationType.ADD;
- }
-
-
+ public abstract Map<ObjectClass,String> getObjectClasses();
/**
- * {@inheritDoc}
+ * Adds the provided objectclass to the entry to add. This should only be
+ * called from pre-operation plugins. Note that pre-operation plugin
+ * processing is invoked after access control and schema validation, so
+ * plugins should be careful to only make changes that will not violate either
+ * schema or access control rules.
+ *
+ * @param objectClass The objectclass to add to the entry.
+ * @param name The name to use for the objectclass.
*/
- @Override()
- public final void disconnectClient(DisconnectReason disconnectReason,
- boolean sendNotification, String message,
- int messageID)
- {
- // Before calling clientConnection.disconnect, we need to mark this
- // operation as cancelled so that the attempt to cancel it later won't cause
- // an unnecessary delay.
- setCancelResult(CancelResult.CANCELED);
-
- clientConnection.disconnect(disconnectReason, sendNotification, message,
- messageID);
- }
-
-
+ public abstract void addObjectClass(ObjectClass objectClass, String name);
/**
- * {@inheritDoc}
+ * Removes the provided objectclass from the entry to add. This should only
+ * be called from pre-operation plugins. Note that pre-operation plugin
+ * processing is invoked after access control and schema validation, so
+ * plugins should be careful to only make changes that will not violate either
+ * schema or access control rules.
+ *
+ * @param objectClass The objectclass to remove from the entry.
*/
- @Override()
- public final String[][] getRequestLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- return new String[][]
- {
- new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }
- };
- }
-
-
+ public abstract void removeObjectClass(ObjectClass objectClass);
/**
- * {@inheritDoc}
+ * Retrieves the set of processed operational attributes for the entry to add.
+ * This should not be called by pre-parse plugins because this information
+ * will not yet be available. The contents of the returned map may be altered
+ * by the caller.
+ *
+ * @return The set of processed operational attributes for the entry to add,
+ * or <CODE>null</CODE> if that information is not yet available.
*/
- @Override()
- public final String[][] getResponseLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- String resultCode = String.valueOf(getResultCode().getIntValue());
-
- String errorMessage;
- StringBuilder errorMessageBuffer = getErrorMessage();
- if (errorMessageBuffer == null)
- {
- errorMessage = null;
- }
- else
- {
- errorMessage = errorMessageBuffer.toString();
- }
-
- String matchedDNStr;
- DN matchedDN = getMatchedDN();
- if (matchedDN == null)
- {
- matchedDNStr = null;
- }
- else
- {
- matchedDNStr = matchedDN.toString();
- }
-
- String referrals;
- List<String> referralURLs = getReferralURLs();
- if ((referralURLs == null) || referralURLs.isEmpty())
- {
- referrals = null;
- }
- else
- {
- StringBuilder buffer = new StringBuilder();
- Iterator<String> iterator = referralURLs.iterator();
- buffer.append(iterator.next());
-
- while (iterator.hasNext())
- {
- buffer.append(", ");
- buffer.append(iterator.next());
- }
-
- referrals = buffer.toString();
- }
-
- String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
-
- return new String[][]
- {
- new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
- new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
- new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
- new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
- new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
- };
- }
-
-
+ public abstract Map<AttributeType,List<Attribute>> getOperationalAttributes();
/**
* Retrieves the proxied authorization DN for this operation if proxied
@@ -714,1914 +209,17 @@
* authorization has been requested, or {@code null} if proxied
* authorization has not been requested.
*/
- public DN getProxiedAuthorizationDN()
- {
- return proxiedAuthorizationDN;
- }
-
-
+ public abstract DN getProxiedAuthorizationDN();
/**
- * {@inheritDoc}
- */
- @Override()
- public final ArrayList<Control> getResponseControls()
- {
- return responseControls;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void addResponseControl(Control control)
- {
- responseControls.add(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void removeResponseControl(Control control)
- {
- responseControls.remove(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void run()
- {
- // Start the processing timer.
- processingStartTime = System.currentTimeMillis();
- setResultCode(ResultCode.UNDEFINED);
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- return;
- }
-
-
- // Get the plugin config manager that will be used for invoking plugins.
- PluginConfigManager pluginConfigManager =
- DirectoryServer.getPluginConfigManager();
- boolean skipPostOperation = false;
-
-
- // Create a labeled block of code that we can break out of if a problem is
- // detected.
-addProcessing:
- {
- // Invoke the pre-parse add plugins.
- PreParsePluginResult preParseResult =
- pluginConfigManager.invokePreParseAddPlugins(this);
- if (preParseResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the request and
- // result and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logAddRequest(this);
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
- else if (preParseResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- logAddRequest(this);
- break addProcessing;
- }
- else if (preParseResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break addProcessing;
- }
-
-
- // Log the add request message.
- logAddRequest(this);
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // Process the entry DN and set of attributes to convert them from their
- // raw forms as provided by the client to the forms required for the rest
- // of the add processing.
- try
- {
- if (entryDN == null)
- {
- entryDN = DN.decode(rawEntryDN);
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break addProcessing;
- }
-
-
- if ((objectClasses == null) || (userAttributes == null) ||
- (operationalAttributes == null))
- {
- objectClasses = new HashMap<ObjectClass,String>();
- userAttributes = new HashMap<AttributeType,List<Attribute>>();
- operationalAttributes = new HashMap<AttributeType,List<Attribute>>();
- for (RawAttribute a : rawAttributes)
- {
- try
- {
- Attribute attr = a.toAttribute();
- AttributeType attrType = attr.getAttributeType();
-
-
- // If the attribute type is marked "NO-USER-MODIFICATION" then fail
- // unless this is an internal operation or is related to
- // synchronization in some way.
- if (attrType.isNoUserModification())
- {
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_ATTR_IS_NO_USER_MOD,
- String.valueOf(entryDN),
- attr.getName()));
- break addProcessing;
- }
- }
-
-
- if (attrType.isObjectClassType())
- {
- for (ByteString os : a.getValues())
- {
- String ocName = os.toString();
- ObjectClass oc =
- DirectoryServer.getObjectClass(toLowerCase(ocName));
- if (oc == null)
- {
- oc = DirectoryServer.getDefaultObjectClass(ocName);
- }
-
- objectClasses.put(oc,ocName);
- }
- }
- else if (attrType.isOperational())
- {
- List<Attribute> attrs = operationalAttributes.get(attrType);
- if (attrs == null)
- {
- attrs = new ArrayList<Attribute>(1);
- attrs.add(attr);
- operationalAttributes.put(attrType, attrs);
- }
- else
- {
- attrs.add(attr);
- }
- }
- else
- {
- List<Attribute> attrs = userAttributes.get(attrType);
- if (attrs == null)
- {
- attrs = new ArrayList<Attribute>(1);
- attrs.add(attr);
- userAttributes.put(attrType, attrs);
- }
- else
- {
- // Check to see if any of the existing attributes in the list
- // have the same set of options. If so, then add the values
- // to that attribute.
- boolean attributeSeen = false;
- for (Attribute ea : attrs)
- {
- if (ea.optionsEqual(attr.getOptions()))
- {
- LinkedHashSet<AttributeValue> valueSet = ea.getValues();
- valueSet.addAll(attr.getValues());
- attributeSeen = true;
- }
- }
- if (!attributeSeen)
- {
- // This is the first occurrence of the attribute and options.
- attrs.add(attr);
- }
- }
- }
- }
- catch (LDAPException le)
- {
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break addProcessing;
- }
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // Grab a read lock on the parent entry, if there is one. We need to do
- // this to ensure that the parent is not deleted or renamed while this add
- // is in progress, and we could also need it to check the entry against
- // a DIT structure rule.
- Lock parentLock = null;
- Lock entryLock = null;
-
- DN parentDN = entryDN.getParentDNInSuffix();
- if (parentDN == null)
- {
- // Either this entry is a suffix or doesn't belong in the directory.
- if (DirectoryServer.isNamingContext(entryDN))
- {
- // This is fine. This entry is one of the configured suffixes.
- parentLock = null;
- }
- else if (entryDN.isNullDN())
- {
- // This is not fine. The root DSE cannot be added.
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_CANNOT_ADD_ROOT_DSE));
- break addProcessing;
- }
- else
- {
- // The entry doesn't have a parent but isn't a suffix. This is not
- // allowed.
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_ADD_ENTRY_NOT_SUFFIX,
- String.valueOf(entryDN)));
- break addProcessing;
- }
- }
- else
- {
- for (int i=0; i < 3; i++)
- {
- parentLock = LockManager.lockRead(parentDN);
- if (parentLock != null)
- {
- break;
- }
- }
-
- if (parentLock == null)
- {
- setResultCode(DirectoryServer.getServerErrorResultCode());
- appendErrorMessage(getMessage(MSGID_ADD_CANNOT_LOCK_PARENT,
- String.valueOf(entryDN),
- String.valueOf(parentDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
- }
-
-
- try
- {
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // Grab a write lock on the target entry. We'll need to do this
- // eventually anyway, and we want to make sure that the two locks are
- // always released when exiting this method, no matter what. Since
- // the entry shouldn't exist yet, locking earlier than necessary
- // shouldn't cause a problem.
- for (int i=0; i < 3; i++)
- {
- entryLock = LockManager.lockWrite(entryDN);
- if (entryLock != null)
- {
- break;
- }
- }
-
- if (entryLock == null)
- {
- setResultCode(DirectoryServer.getServerErrorResultCode());
- appendErrorMessage(getMessage(MSGID_ADD_CANNOT_LOCK_ENTRY,
- String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
-
-
- // Invoke any conflict resolution processing that might be needed by the
- // synchronization provider.
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.handleConflictResolution(this);
- if (! result.continueOperationProcessing())
- {
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_ADD_SYNCH_CONFLICT_RESOLUTION_FAILED,
- getConnectionID(), getOperationID(),
- getExceptionMessage(de));
-
- setResponseData(de);
- break addProcessing;
- }
- }
-
-
- // Check to see if the entry already exists. We do this before
- // checking whether the parent exists to ensure a referral entry
- // above the parent results in a correct referral.
- try
- {
- if (DirectoryServer.entryExists(entryDN))
- {
- setResultCode(ResultCode.ENTRY_ALREADY_EXISTS);
- appendErrorMessage(getMessage(MSGID_ADD_ENTRY_ALREADY_EXISTS,
- String.valueOf(entryDN)));
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
- break addProcessing;
- }
-
-
- // Get the parent entry, if it exists.
- Entry parentEntry = null;
- if (parentDN != null)
- {
- try
- {
- parentEntry = DirectoryServer.getEntry(parentDN);
-
- if (parentEntry == null)
- {
- DN matchedDN = parentDN.getParentDNInSuffix();
- while (matchedDN != null)
- {
- try
- {
- if (DirectoryServer.entryExists(matchedDN))
- {
- setMatchedDN(matchedDN);
- break;
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- break;
- }
-
- matchedDN = matchedDN.getParentDNInSuffix();
- }
-
-
- // The parent doesn't exist, so this add can't be successful.
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_ADD_NO_PARENT,
- String.valueOf(entryDN),
- String.valueOf(parentDN)));
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
- break addProcessing;
- }
- }
-
-
- // Check to make sure that all of the RDN attributes are included as
- // attribute values. If not, then either add them or report an error.
- RDN rdn = entryDN.getRDN();
- int numAVAs = rdn.getNumValues();
- for (int i=0; i < numAVAs; i++)
- {
- AttributeType t = rdn.getAttributeType(i);
- AttributeValue v = rdn.getAttributeValue(i);
- String n = rdn.getAttributeName(i);
- if (t.isOperational())
- {
- List<Attribute> attrList = operationalAttributes.get(t);
- if (attrList == null)
- {
- if (isSynchronizationOperation() ||
- DirectoryServer.addMissingRDNAttributes())
- {
- LinkedHashSet<AttributeValue> valueList =
- new LinkedHashSet<AttributeValue>(1);
- valueList.add(v);
-
- attrList = new ArrayList<Attribute>();
- attrList.add(new Attribute(t, n, valueList));
-
- operationalAttributes.put(t, attrList);
- }
- else
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- n));
-
- break addProcessing;
- }
- }
- else
- {
- boolean found = false;
- for (Attribute a : attrList)
- {
- if (a.hasOptions())
- {
- continue;
- }
- else
- {
- if (! a.hasValue(v))
- {
- a.getValues().add(v);
- }
-
- found = true;
- break;
- }
- }
-
- if (! found)
- {
- if (isSynchronizationOperation() ||
- DirectoryServer.addMissingRDNAttributes())
- {
- LinkedHashSet<AttributeValue> valueList =
- new LinkedHashSet<AttributeValue>(1);
- valueList.add(v);
- attrList.add(new Attribute(t, n, valueList));
- }
- else
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- n));
-
- break addProcessing;
- }
- }
- }
- }
- else
- {
- List<Attribute> attrList = userAttributes.get(t);
- if (attrList == null)
- {
- if (isSynchronizationOperation() ||
- DirectoryServer.addMissingRDNAttributes())
- {
- LinkedHashSet<AttributeValue> valueList =
- new LinkedHashSet<AttributeValue>(1);
- valueList.add(v);
-
- attrList = new ArrayList<Attribute>();
- attrList.add(new Attribute(t, n, valueList));
-
- userAttributes.put(t, attrList);
- }
- else
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- n));
-
- break addProcessing;
- }
- }
- else
- {
- boolean found = false;
- for (Attribute a : attrList)
- {
- if (a.hasOptions())
- {
- continue;
- }
- else
- {
- if (! a.hasValue(v))
- {
- a.getValues().add(v);
- }
-
- found = true;
- break;
- }
- }
-
- if (! found)
- {
- if (isSynchronizationOperation() ||
- DirectoryServer.addMissingRDNAttributes())
- {
- LinkedHashSet<AttributeValue> valueList =
- new LinkedHashSet<AttributeValue>(1);
- valueList.add(v);
- attrList.add(new Attribute(t, n, valueList));
- }
- else
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_ADD_MISSING_RDN_ATTRIBUTE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- n));
-
- break addProcessing;
- }
- }
- }
- }
- }
-
-
- // Check to make sure that all objectclasses have their superior classes
- // listed in the entry. If not, then add them.
- HashSet<ObjectClass> additionalClasses = null;
- for (ObjectClass oc : objectClasses.keySet())
- {
- ObjectClass superiorClass = oc.getSuperiorClass();
- if ((superiorClass != null) &&
- (! objectClasses.containsKey(superiorClass)))
- {
- if (additionalClasses == null)
- {
- additionalClasses = new HashSet<ObjectClass>();
- }
-
- additionalClasses.add(superiorClass);
- }
- }
-
- if (additionalClasses != null)
- {
- for (ObjectClass oc : additionalClasses)
- {
- addObjectClassChain(oc);
- }
- }
-
-
- // Create an entry object to encapsulate the set of attributes and
- // objectclasses.
- entry = new Entry(entryDN, objectClasses, userAttributes,
- operationalAttributes);
-
-
- // Check to see if the entry includes a privilege specification. If so,
- // then the requester must have the PRIVILEGE_CHANGE privilege.
- AttributeType privType =
- DirectoryServer.getAttributeType(OP_ATTR_PRIVILEGE_NAME, true);
- if (entry.hasAttribute(privType) &&
- (! clientConnection.hasPrivilege(Privilege.PRIVILEGE_CHANGE, this)))
- {
- int msgID = MSGID_ADD_CHANGE_PRIVILEGE_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
- break addProcessing;
- }
-
- // If it's not a synchronization operation, then check
- // to see if the entry contains one or more passwords and if they
- // are valid in accordance with the password policies associated with
- // the user. Also perform any encoding that might be required by
- // password storage schemes.
- if (! isSynchronizationOperation())
- {
- // FIXME -- We need to check to see if the password policy subentry
- // might be specified virtually rather than as a real
- // attribute.
- PasswordPolicy pwPolicy = null;
- List<Attribute> pwAttrList =
- entry.getAttribute(OP_ATTR_PWPOLICY_POLICY_DN);
- if ((pwAttrList != null) && (! pwAttrList.isEmpty()))
- {
- Attribute a = pwAttrList.get(0);
- LinkedHashSet<AttributeValue> valueSet = a.getValues();
- Iterator<AttributeValue> iterator = valueSet.iterator();
- if (iterator.hasNext())
- {
- DN policyDN;
- try
- {
- policyDN = DN.decode(iterator.next().getValue());
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- int msgID = MSGID_ADD_INVALID_PWPOLICY_DN_SYNTAX;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- de.getErrorMessage()));
-
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
- break addProcessing;
- }
-
- pwPolicy = DirectoryServer.getPasswordPolicy(policyDN);
- if (pwPolicy == null)
- {
- int msgID = MSGID_ADD_NO_SUCH_PWPOLICY;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- String.valueOf(policyDN)));
-
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- break addProcessing;
- }
- }
- }
-
- if (pwPolicy == null)
- {
- pwPolicy = DirectoryServer.getDefaultPasswordPolicy();
- }
-
- try
- {
- handlePasswordPolicy(pwPolicy, entry);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResponseData(de);
- break addProcessing;
- }
- }
-
-
- // Check to see if the entry is valid according to the server schema,
- // and also whether its attributes are valid according to their syntax.
- if (DirectoryServer.checkSchema())
- {
- StringBuilder invalidReason = new StringBuilder();
- if (! entry.conformsToSchema(parentEntry, true, true, true,
- invalidReason))
- {
- setResultCode(ResultCode.OBJECTCLASS_VIOLATION);
- setErrorMessage(invalidReason);
- break addProcessing;
- }
- else
- {
- switch (DirectoryServer.getSyntaxEnforcementPolicy())
- {
- case REJECT:
- invalidReason = new StringBuilder();
- for (List<Attribute> attrList : userAttributes.values())
- {
- for (Attribute a : attrList)
- {
- AttributeSyntax syntax = a.getAttributeType().getSyntax();
- if (syntax != null)
- {
- for (AttributeValue v : a.getValues())
- {
- if (! syntax.valueIsAcceptable(v.getValue(),
- invalidReason))
- {
- String message =
- getMessage(MSGID_ADD_OP_INVALID_SYNTAX,
- String.valueOf(entryDN),
- String.valueOf(v.getStringValue()),
- String.valueOf(a.getName()),
- String.valueOf(invalidReason));
- invalidReason = new StringBuilder(message);
-
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
- setErrorMessage(invalidReason);
- break addProcessing;
- }
- }
- }
- }
- }
-
- for (List<Attribute> attrList :
- operationalAttributes.values())
- {
- for (Attribute a : attrList)
- {
- AttributeSyntax syntax = a.getAttributeType().getSyntax();
- if (syntax != null)
- {
- for (AttributeValue v : a.getValues())
- {
- if (! syntax.valueIsAcceptable(v.getValue(),
- invalidReason))
- {
- String message =
- getMessage(MSGID_ADD_OP_INVALID_SYNTAX,
- String.valueOf(entryDN),
- String.valueOf(v.getStringValue()),
- String.valueOf(a.getName()),
- String.valueOf(invalidReason));
- invalidReason = new StringBuilder(message);
-
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
- setErrorMessage(invalidReason);
- break addProcessing;
- }
- }
- }
- }
- }
-
- break;
-
-
- case WARN:
- invalidReason = new StringBuilder();
- for (List<Attribute> attrList : userAttributes.values())
- {
- for (Attribute a : attrList)
- {
- AttributeSyntax syntax = a.getAttributeType().getSyntax();
- if (syntax != null)
- {
- for (AttributeValue v : a.getValues())
- {
- if (! syntax.valueIsAcceptable(v.getValue(),
- invalidReason))
- {
- logError(ErrorLogCategory.SCHEMA,
- ErrorLogSeverity.SEVERE_WARNING,
- MSGID_ADD_OP_INVALID_SYNTAX,
- String.valueOf(entryDN),
- String.valueOf(v.getStringValue()),
- String.valueOf(a.getName()),
- String.valueOf(invalidReason));
- }
- }
- }
- }
- }
-
- for (List<Attribute> attrList : operationalAttributes.values())
- {
- for (Attribute a : attrList)
- {
- AttributeSyntax syntax = a.getAttributeType().getSyntax();
- if (syntax != null)
- {
- for (AttributeValue v : a.getValues())
- {
- if (! syntax.valueIsAcceptable(v.getValue(),
- invalidReason))
- {
- logError(ErrorLogCategory.SCHEMA,
- ErrorLogSeverity.SEVERE_WARNING,
- MSGID_ADD_OP_INVALID_SYNTAX,
- String.valueOf(entryDN),
- String.valueOf(v.getStringValue()),
- String.valueOf(a.getName()),
- String.valueOf(invalidReason));
- }
- }
- }
- }
- }
-
- break;
- }
- }
-
-
- // See if the entry contains any attributes or object classes marked
- // OBSOLETE. If so, then reject the entry.
- for (AttributeType at : userAttributes.keySet())
- {
- if (at.isObsolete())
- {
- int msgID = MSGID_ADD_ATTR_IS_OBSOLETE;
- String message = getMessage(msgID, String.valueOf(entryDN),
- at.getNameOrOID());
- appendErrorMessage(message);
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- break addProcessing;
- }
- }
-
- for (AttributeType at : operationalAttributes.keySet())
- {
- if (at.isObsolete())
- {
- int msgID = MSGID_ADD_ATTR_IS_OBSOLETE;
- String message = getMessage(msgID, String.valueOf(entryDN),
- at.getNameOrOID());
- appendErrorMessage(message);
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- break addProcessing;
- }
- }
-
- for (ObjectClass oc : objectClasses.keySet())
- {
- if (oc.isObsolete())
- {
- int msgID = MSGID_ADD_OC_IS_OBSOLETE;
- String message = getMessage(msgID, String.valueOf(entryDN),
- oc.getNameOrOID());
- appendErrorMessage(message);
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- break addProcessing;
- }
- }
- }
-
- // Check to see if there are any controls in the request. If so,
- // then
- // see if there is any special processing required.
- boolean noOp = false;
- LDAPPostReadRequestControl postReadRequest = null;
- List<Control> requestControls = getRequestControls();
- if ((requestControls != null) && (! requestControls.isEmpty()))
- {
- for (int i=0; i < requestControls.size(); i++)
- {
- Control c = requestControls.get(i);
- String oid = c.getOID();
-
- if (oid.equals(OID_LDAP_ASSERTION))
- {
- LDAPAssertionRequestControl assertControl;
- if (c instanceof LDAPAssertionRequestControl)
- {
- assertControl = (LDAPAssertionRequestControl) c;
- }
- else
- {
- try
- {
- assertControl = LDAPAssertionRequestControl.decodeControl(c);
- requestControls.set(i, assertControl);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break addProcessing;
- }
- }
-
- try
- {
- // FIXME -- We need to determine whether the current user has
- // permission to make this determination.
- SearchFilter filter = assertControl.getSearchFilter();
- if (! filter.matchesEntry(entry))
- {
- setResultCode(ResultCode.ASSERTION_FAILED);
-
- appendErrorMessage(getMessage(MSGID_ADD_ASSERTION_FAILED,
- String.valueOf(entryDN)));
-
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(ResultCode.PROTOCOL_ERROR);
-
- int msgID = MSGID_ADD_CANNOT_PROCESS_ASSERTION_FILTER;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- de.getErrorMessage()));
-
- break addProcessing;
- }
- }
- else if (oid.equals(OID_LDAP_NOOP_OPENLDAP_ASSIGNED))
- {
- noOp = true;
- }
- else if (oid.equals(OID_LDAP_READENTRY_POSTREAD))
- {
- if (c instanceof LDAPAssertionRequestControl)
- {
- postReadRequest = (LDAPPostReadRequestControl) c;
- }
- else
- {
- try
- {
- postReadRequest = LDAPPostReadRequestControl.decodeControl(c);
- requestControls.set(i, postReadRequest);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break addProcessing;
- }
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V1))
- {
- // The requester must have the PROXIED_AUTH privilige in order to
- // be able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break addProcessing;
- }
-
-
- ProxiedAuthV1Control proxyControl;
- if (c instanceof ProxiedAuthV1Control)
- {
- proxyControl = (ProxiedAuthV1Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV1Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break addProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break addProcessing;
- }
-
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_ADD_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V2))
- {
- // The requester must have the PROXIED_AUTH privilige in order to
- // be able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break addProcessing;
- }
-
-
- ProxiedAuthV2Control proxyControl;
- if (c instanceof ProxiedAuthV2Control)
- {
- proxyControl = (ProxiedAuthV2Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV2Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break addProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break addProcessing;
- }
-
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_ADD_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
-
- // NYI -- Add support for additional controls.
- else if (c.isCritical())
- {
- Backend backend = DirectoryServer.getBackend(entryDN);
- if ((backend == null) || (! backend.supportsControl(oid)))
- {
- setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
-
- int msgID = MSGID_ADD_UNSUPPORTED_CRITICAL_CONTROL;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- oid));
-
- break addProcessing;
- }
- }
- }
- }
-
-
- // Check to see if the client has permission to perform the add.
-
- // FIXME: for now assume that this will check all permission
- // pertinent to the operation. This includes proxy authorization
- // and any other controls specified.
-
- // FIXME: earlier checks to see if the entry already exists or
- // if the parent entry does not exist may have already exposed
- // sensitive information to the client.
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isAllowed(this) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_ADD_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break addProcessing;
- }
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // If the operation is not a synchronization operation,
- // Invoke the pre-operation modify plugins.
- if (!isSynchronizationOperation())
- {
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationAddPlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result
- // and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break addProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break addProcessing;
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
-
-
- // Actually perform the add operation. This should also include taking
- // care of any synchronization that might be needed.
- Backend backend = DirectoryServer.getBackend(entryDN);
- if (backend == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage("No backend for entry " + entryDN.toString());
- }
- else
- {
- // If it is not a private backend, then check to see if the server or
- // backend is operating in read-only mode.
- if (! backend.isPrivateBackend())
- {
- switch (DirectoryServer.getWritabilityMode())
- {
- case DISABLED:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_SERVER_READONLY,
- String.valueOf(entryDN)));
- break addProcessing;
-
- case INTERNAL_ONLY:
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_SERVER_READONLY,
- String.valueOf(entryDN)));
- break addProcessing;
- }
- }
-
- switch (backend.getWritabilityMode())
- {
- case DISABLED:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_BACKEND_READONLY,
- String.valueOf(entryDN)));
- break addProcessing;
-
- case INTERNAL_ONLY:
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_ADD_BACKEND_READONLY,
- String.valueOf(entryDN)));
- break addProcessing;
- }
- }
- }
-
-
- try
- {
- if (noOp)
- {
- appendErrorMessage(getMessage(MSGID_ADD_NOOP));
-
- // FIXME -- We must set a result code other than SUCCESS.
- }
- else
- {
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.doPreOperation(this);
- if (! result.continueOperationProcessing())
- {
- break addProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_ADD_SYNCH_PREOP_FAILED, getConnectionID(),
- getOperationID(), getExceptionMessage(de));
-
- setResponseData(de);
- break addProcessing;
- }
- }
-
- backend.addEntry(entry, this);
- }
-
- if (postReadRequest != null)
- {
- Entry addedEntry = entry.duplicate(true);
-
- if (! postReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- addedEntry.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! postReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- addedEntry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! postReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- addedEntry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // FIXME -- Check access controls on the entry to see if it should
- // be returned or if any attributes need to be stripped
- // out..
- SearchResultEntry searchEntry = new SearchResultEntry(addedEntry);
- LDAPPostReadResponseControl responseControl =
- new LDAPPostReadResponseControl(postReadRequest.getOID(),
- postReadRequest.isCritical(),
- searchEntry);
-
- responseControls.add(responseControl);
- }
-
- setResultCode(ResultCode.SUCCESS);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break addProcessing;
- }
- catch (CancelledOperationException coe)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, coe);
- }
-
- CancelResult cancelResult = coe.getCancelResult();
-
- setCancelResult(cancelResult);
- setResultCode(cancelResult.getResultCode());
-
- String message = coe.getMessage();
- if ((message != null) && (message.length() > 0))
- {
- appendErrorMessage(message);
- }
-
- break addProcessing;
- }
- }
- }
- finally
- {
- if (entryLock != null)
- {
- LockManager.unlock(entryDN, entryLock);
- }
-
- if (parentLock != null)
- {
- LockManager.unlock(parentDN, parentLock);
- }
-
-
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- provider.doPostOperation(this);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_ADD_SYNCH_POSTOP_FAILED, getConnectionID(),
- getOperationID(), getExceptionMessage(de));
-
- setResponseData(de);
- break;
- }
- }
- }
- }
-
-
- // Indicate that it is now too late to attempt to cancel the operation.
- setCancelResult(CancelResult.TOO_LATE);
-
-
- // Invoke the post-operation add plugins.
- if (! skipPostOperation)
- {
- // FIXME -- Should this also be done while holding the locks?
- PostOperationPluginResult postOpResult =
- pluginConfigManager.invokePostOperationAddPlugins(this);
- if (postOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result and
- // return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logAddResponse(this);
- pluginConfigManager.invokePostResponseAddPlugins(this);
- return;
- }
- }
-
-
- // Notify any change notification listeners that might be registered with
- // the server.
- if ((getResultCode() == ResultCode.SUCCESS) && (entry != null))
- {
- for (ChangeNotificationListener changeListener :
- DirectoryServer.getChangeNotificationListeners())
- {
- try
- {
- changeListener.handleAddOperation(this, entry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_ADD_ERROR_NOTIFYING_CHANGE_LISTENER;
- String message = getMessage(msgID, getExceptionMessage(e));
- logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
- }
- }
- }
-
-
- // Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
-
-
- // Send the add response to the client.
- getClientConnection().sendResponse(this);
-
-
- // Log the add response.
- logAddResponse(this);
-
-
- // Notify any persistent searches that might be registered with the server.
- if ((getResultCode() == ResultCode.SUCCESS) && (entry != null))
- {
- for (PersistentSearch persistentSearch :
- DirectoryServer.getPersistentSearches())
- {
- try
- {
- persistentSearch.processAdd(this, entry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_ADD_ERROR_NOTIFYING_PERSISTENT_SEARCH;
- String message = getMessage(msgID, String.valueOf(persistentSearch),
- getExceptionMessage(e));
- logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
-
- DirectoryServer.deregisterPersistentSearch(persistentSearch);
- }
- }
- }
-
-
- // Invoke the post-response add plugins.
- pluginConfigManager.invokePostResponseAddPlugins(this);
- }
-
-
-
- /**
- * Adds the provided objectClass to the entry, along with its superior classes
- * if appropriate.
+ * Set the proxied authorization DN for this operation if proxied
+ * authorization has been requested.
*
- * @param objectClass The objectclass to add to the entry.
+ * @param proxiedAuthorizationDN
+ * The proxied authorization DN for this operation if proxied
+ * authorization has been requested, or {@code null} if proxied
+ * authorization has not been requested.
*/
- private final void addObjectClassChain(ObjectClass objectClass)
- {
- if (! objectClasses.containsKey(objectClass))
- {
- objectClasses.put(objectClass, objectClass.getNameOrOID());
- }
+ public abstract void setProxiedAuthorizationDN(DN proxiedAuthorizationDN);
- ObjectClass superiorClass = objectClass.getSuperiorClass();
- if ((superiorClass != null) &&
- (! objectClasses.containsKey(superiorClass)))
- {
- addObjectClassChain(superiorClass);
- }
- }
-
-
-
- /**
- * Performs all password policy processing necessary for the provided add
- * operation.
- *
- * @param passwordPolicy The password policy associated with the entry to be
- * added.
- * @param userEntry The user entry being added.
- *
- * @throws DirectoryException If a problem occurs while performing password
- * policy processing for the add operation.
- */
- private final void handlePasswordPolicy(PasswordPolicy passwordPolicy,
- Entry userEntry)
- throws DirectoryException
- {
- // See if a password was specified.
- AttributeType passwordAttribute = passwordPolicy.getPasswordAttribute();
- List<Attribute> attrList = userEntry.getAttribute(passwordAttribute);
- if ((attrList == null) || attrList.isEmpty())
- {
- // The entry doesn't have a password, so no action is required.
- return;
- }
- else if (attrList.size() > 1)
- {
- // This must mean there are attribute options, which we won't allow for
- // passwords.
- int msgID = MSGID_PWPOLICY_ATTRIBUTE_OPTIONS_NOT_ALLOWED;
- String message = getMessage(msgID, passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message,
- msgID);
- }
-
- Attribute passwordAttr = attrList.get(0);
- if (passwordAttr.hasOptions())
- {
- int msgID = MSGID_PWPOLICY_ATTRIBUTE_OPTIONS_NOT_ALLOWED;
- String message = getMessage(msgID, passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message,
- msgID);
- }
-
- LinkedHashSet<AttributeValue> values = passwordAttr.getValues();
- if (values.isEmpty())
- {
- // This will be treated the same as not having a password.
- return;
- }
-
- if ((! passwordPolicy.allowMultiplePasswordValues()) && (values.size() > 1))
- {
- // FIXME -- What if they're pre-encoded and might all be the same?
- int msgID = MSGID_PWPOLICY_MULTIPLE_PW_VALUES_NOT_ALLOWED;
- String message = getMessage(msgID, passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message,
- msgID);
- }
-
- CopyOnWriteArrayList<PasswordStorageScheme> defaultStorageSchemes =
- passwordPolicy.getDefaultStorageSchemes();
- LinkedHashSet<AttributeValue> newValues =
- new LinkedHashSet<AttributeValue>(defaultStorageSchemes.size());
- for (AttributeValue v : values)
- {
- ByteString value = v.getValue();
-
- // See if the password is pre-encoded.
- if (passwordPolicy.usesAuthPasswordSyntax())
- {
- if (AuthPasswordSyntax.isEncoded(value))
- {
- if (passwordPolicy.allowPreEncodedPasswords())
- {
- newValues.add(v);
- continue;
- }
- else
- {
- int msgID = MSGID_PWPOLICY_PREENCODED_NOT_ALLOWED;
- String message = getMessage(msgID,
- passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- message, msgID);
- }
- }
- }
- else
- {
- if (UserPasswordSyntax.isEncoded(value))
- {
- if (passwordPolicy.allowPreEncodedPasswords())
- {
- newValues.add(v);
- continue;
- }
- else
- {
- int msgID = MSGID_PWPOLICY_PREENCODED_NOT_ALLOWED;
- String message = getMessage(msgID,
- passwordAttribute.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- message, msgID);
- }
- }
- }
-
-
- // See if the password passes validation. We should only do this if
- // validation should be performed for administrators.
- if (! passwordPolicy.skipValidationForAdministrators())
- {
- // There are never any current passwords for an add operation.
- HashSet<ByteString> currentPasswords = new HashSet<ByteString>(0);
- StringBuilder invalidReason = new StringBuilder();
- for (PasswordValidator<?> validator :
- passwordPolicy.getPasswordValidators().values())
- {
- if (! validator.passwordIsAcceptable(value, currentPasswords, this,
- userEntry, invalidReason))
- {
- int msgID = MSGID_PWPOLICY_VALIDATION_FAILED;
- String message = getMessage(msgID, passwordAttribute.getNameOrOID(),
- String.valueOf(invalidReason));
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- message, msgID);
- }
- }
- }
-
-
- // Encode the password.
- if (passwordPolicy.usesAuthPasswordSyntax())
- {
- for (PasswordStorageScheme s : defaultStorageSchemes)
- {
- ByteString encodedValue = s.encodeAuthPassword(value);
- newValues.add(new AttributeValue(passwordAttribute, encodedValue));
- }
- }
- else
- {
- for (PasswordStorageScheme s : defaultStorageSchemes)
- {
- ByteString encodedValue = s.encodePasswordWithScheme(value);
- newValues.add(new AttributeValue(passwordAttribute, encodedValue));
- }
- }
- }
-
-
- // Put the new encoded values in the entry.
- passwordAttr.setValues(newValues);
-
-
- // Set the password changed time attribute.
- ByteString timeString =
- new ASN1OctetString(TimeThread.getGeneralizedTime());
- AttributeType changedTimeType =
- DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_CHANGED_TIME_LC);
- if (changedTimeType == null)
- {
- changedTimeType = DirectoryServer.getDefaultAttributeType(
- OP_ATTR_PWPOLICY_CHANGED_TIME);
- }
-
- LinkedHashSet<AttributeValue> changedTimeValues =
- new LinkedHashSet<AttributeValue>(1);
- changedTimeValues.add(new AttributeValue(changedTimeType, timeString));
-
- ArrayList<Attribute> changedTimeList = new ArrayList<Attribute>(1);
- changedTimeList.add(new Attribute(changedTimeType,
- OP_ATTR_PWPOLICY_CHANGED_TIME,
- changedTimeValues));
-
- userEntry.putAttribute(changedTimeType, changedTimeList);
-
-
- // If we should force change on add, then set the appropriate flag.
- if (passwordPolicy.forceChangeOnAdd())
- {
- AttributeType resetType =
- DirectoryServer.getAttributeType(OP_ATTR_PWPOLICY_RESET_REQUIRED_LC);
- if (resetType == null)
- {
- resetType = DirectoryServer.getDefaultAttributeType(
- OP_ATTR_PWPOLICY_RESET_REQUIRED);
- }
-
- LinkedHashSet<AttributeValue> resetValues = new
- LinkedHashSet<AttributeValue>(1);
- resetValues.add(BooleanSyntax.createBooleanValue(true));
-
- ArrayList<Attribute> resetList = new ArrayList<Attribute>(1);
- resetList.add(new Attribute(resetType, OP_ATTR_PWPOLICY_RESET_REQUIRED,
- resetValues));
- userEntry.putAttribute(resetType, resetList);
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelResult cancel(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
-
- CancelResult cancelResult = getCancelResult();
- long stopWaitingTime = System.currentTimeMillis() + 5000;
- while ((cancelResult == null) &&
- (System.currentTimeMillis() < stopWaitingTime))
- {
- try
- {
- Thread.sleep(50);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
-
- cancelResult = getCancelResult();
- }
-
- if (cancelResult == null)
- {
- // This can happen in some rare cases (e.g., if a client disconnects and
- // there is still a lot of data to send to that client), and in this case
- // we'll prevent the cancel thread from blocking for a long period of
- // time.
- cancelResult = CancelResult.CANNOT_CANCEL;
- }
-
- return cancelResult;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelRequest getCancelRequest()
- {
- return cancelRequest;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
- return true;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void toString(StringBuilder buffer)
- {
- buffer.append("AddOperation(connID=");
- buffer.append(clientConnection.getConnectionID());
- buffer.append(", opID=");
- buffer.append(operationID);
- buffer.append(", dn=");
- buffer.append(rawEntryDN);
- buffer.append(")");
- }
-}
-
+}
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/AddOperationBasis.java b/opendj-sdk/opends/src/server/org/opends/server/core/AddOperationBasis.java
new file mode 100644
index 0000000..59a9e79
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/AddOperationBasis.java
@@ -0,0 +1,1024 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+
+import static org.opends.server.config.ConfigConstants.ATTR_OBJECTCLASS;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ENTRY_DN;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ERROR_MESSAGE;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_MATCHED_DN;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_PROCESSING_TIME;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_REFERRAL_URLS;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_RESULT_CODE;
+import static org.opends.server.loggers.AccessLogger.logAddRequest;
+import static org.opends.server.loggers.AccessLogger.logAddResponse;
+import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.messages.CoreMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.getExceptionMessage;
+import static org.opends.server.util.StaticUtils.toLowerCase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.plugin.PreParsePluginResult;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.ldap.LDAPAttribute;
+import org.opends.server.types.Entry;
+import org.opends.server.types.ErrorLogCategory;
+import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.LDAPException;
+import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.RawAttribute;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.operation.PostResponseAddOperation;
+import org.opends.server.types.operation.PreParseAddOperation;
+import org.opends.server.workflowelement.localbackend.LocalBackendAddOperation;
+
+
+
+
+/**
+ * This class defines an operation that may be used to add a new entry to the
+ * Directory Server.
+ */
+public class AddOperationBasis
+ extends AbstractOperation
+ implements PreParseAddOperation, AddOperation, Runnable,
+ PostResponseAddOperation
+{
+
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
+
+ // The set of response controls to send to the client.
+ private ArrayList<Control> responseControls;
+
+ // The raw, unprocessed entry DN as provided in the request. This may or may
+ // not be a valid DN.
+ private ByteString rawEntryDN;
+
+ // The cancel request that has been issued for this add operation.
+ private CancelRequest cancelRequest;
+
+ // The processed DN of the entry to add.
+ private DN entryDN;
+
+ // The proxied authorization target DN for this operation.
+ private DN proxiedAuthorizationDN;
+
+ // The set of attributes (including the objectclass attribute) in a raw,
+ // unprocessed form as provided in the request. One or more of these
+ // attributes may be invalid.
+ private List<RawAttribute> rawAttributes;
+
+ // The set of operational attributes for the entry to add.
+ private Map<AttributeType,List<Attribute>> operationalAttributes;
+
+ // The set of user attributes for the entry to add.
+ private Map<AttributeType,List<Attribute>> userAttributes;
+
+ // The set of objectclasses for the entry to add.
+ private Map<ObjectClass,String> objectClasses;
+
+ // The change number that has been assigned to this operation.
+ private long changeNumber;
+
+
+ /**
+ * Creates a new add operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param rawEntryDN The raw DN of the entry to add from the client
+ * request. This may or may not be a valid DN.
+ * @param rawAttributes The raw set of attributes from the client
+ * request (including the objectclass attribute).
+ * This may contain invalid attributes.
+ */
+ public AddOperationBasis(ClientConnection clientConnection, long operationID,
+ int messageID, List<Control> requestControls,
+ ByteString rawEntryDN, List<RawAttribute> rawAttributes)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.rawEntryDN = rawEntryDN;
+ this.rawAttributes = rawAttributes;
+
+ responseControls = new ArrayList<Control>();
+ cancelRequest = null;
+ entryDN = null;
+ userAttributes = null;
+ operationalAttributes = null;
+ objectClasses = null;
+ proxiedAuthorizationDN = null;
+ changeNumber = -1;
+ }
+
+
+
+ /**
+ * Creates a new add operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this
+ * operation is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which
+ * this operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param entryDN The DN for the entry.
+ * @param objectClasses The set of objectclasses for the entry.
+ * @param userAttributes The set of user attributes for the entry.
+ * @param operationalAttributes The set of operational attributes for the
+ * entry.
+ */
+ public AddOperationBasis(ClientConnection clientConnection, long operationID,
+ int messageID, List<Control> requestControls,
+ DN entryDN, Map<ObjectClass,String> objectClasses,
+ Map<AttributeType,List<Attribute>> userAttributes,
+ Map<AttributeType,List<Attribute>> operationalAttributes)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.entryDN = entryDN;
+ this.objectClasses = objectClasses;
+ this.userAttributes = userAttributes;
+ this.operationalAttributes = operationalAttributes;
+
+ rawEntryDN = new ASN1OctetString(entryDN.toString());
+
+ rawAttributes = new ArrayList<RawAttribute>();
+
+ ArrayList<ASN1OctetString> ocValues = new ArrayList<ASN1OctetString>();
+ for (String s : objectClasses.values())
+ {
+ ocValues.add(new ASN1OctetString(s));
+ }
+
+ LDAPAttribute ocAttr = new LDAPAttribute(ATTR_OBJECTCLASS, ocValues);
+ rawAttributes.add(ocAttr);
+
+ for (List<Attribute> attrList : userAttributes.values())
+ {
+ for (Attribute a : attrList)
+ {
+ rawAttributes.add(new LDAPAttribute(a));
+ }
+ }
+
+ for (List<Attribute> attrList : operationalAttributes.values())
+ {
+ for (Attribute a : attrList)
+ {
+ rawAttributes.add(new LDAPAttribute(a));
+ }
+ }
+
+ responseControls = new ArrayList<Control>();
+ proxiedAuthorizationDN = null;
+ cancelRequest = null;
+ changeNumber = -1;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ByteString getRawEntryDN()
+ {
+ return rawEntryDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawEntryDN(ByteString rawEntryDN)
+ {
+ this.rawEntryDN = rawEntryDN;
+
+ entryDN = null;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getEntryDN()
+ {
+ try
+ {
+ if (entryDN == null)
+ {
+ entryDN = DN.decode(rawEntryDN);
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResultCode(de.getResultCode());
+ appendErrorMessage(de.getErrorMessage());
+ setMatchedDN(de.getMatchedDN());
+ setReferralURLs(de.getReferralURLs());
+ }
+ return entryDN;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final List<RawAttribute> getRawAttributes()
+ {
+ return rawAttributes;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void addRawAttribute(RawAttribute rawAttribute)
+ {
+ rawAttributes.add(rawAttribute);
+
+ objectClasses = null;
+ userAttributes = null;
+ operationalAttributes = null;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawAttributes(List<RawAttribute> rawAttributes)
+ {
+ this.rawAttributes = rawAttributes;
+
+ objectClasses = null;
+ userAttributes = null;
+ operationalAttributes = null;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Map<ObjectClass,String> getObjectClasses()
+ {
+ if (objectClasses == null){
+ computeObjectClassesAndAttributes();
+ }
+ return objectClasses;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void addObjectClass(ObjectClass objectClass, String name)
+ {
+ objectClasses.put(objectClass, name);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void removeObjectClass(ObjectClass objectClass)
+ {
+ objectClasses.remove(objectClass);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Map<AttributeType,List<Attribute>> getUserAttributes()
+ {
+ if (userAttributes == null){
+ computeObjectClassesAndAttributes();
+ }
+ return userAttributes;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Map<AttributeType,List<Attribute>> getOperationalAttributes()
+ {
+ if (operationalAttributes == null){
+ computeObjectClassesAndAttributes();
+ }
+ return operationalAttributes;
+ }
+
+ /**
+ * Build the objectclasses, the user attributes and the operational attributes
+ * if there are not already computed.
+ */
+ private final void computeObjectClassesAndAttributes()
+ {
+ if ((objectClasses == null) || (userAttributes == null) ||
+ (operationalAttributes == null))
+ {
+ objectClasses = new HashMap<ObjectClass,String>();
+ userAttributes = new HashMap<AttributeType,List<Attribute>>();
+ operationalAttributes = new HashMap<AttributeType,List<Attribute>>();
+
+ for (RawAttribute a : rawAttributes)
+ {
+ try
+ {
+ Attribute attr = a.toAttribute();
+ AttributeType attrType = attr.getAttributeType();
+
+ // If the attribute type is marked "NO-USER-MODIFICATION" then fail
+ // unless this is an internal operation or is related to
+ // synchronization in some way.
+ if (attrType.isNoUserModification())
+ {
+ if (! (isInternalOperation() || isSynchronizationOperation()))
+ {
+ setResultCode(ResultCode.UNWILLING_TO_PERFORM);
+ appendErrorMessage(getMessage(MSGID_ADD_ATTR_IS_NO_USER_MOD,
+ String.valueOf(entryDN),
+ attr.getName()));
+
+ objectClasses = null;
+ userAttributes = null;
+ operationalAttributes = null;
+ return;
+ }
+ }
+
+ if (attrType.isObjectClassType())
+ {
+ for (ByteString os : a.getValues())
+ {
+ String ocName = os.toString();
+ ObjectClass oc =
+ DirectoryServer.getObjectClass(toLowerCase(ocName));
+ if (oc == null)
+ {
+ oc = DirectoryServer.getDefaultObjectClass(ocName);
+ }
+
+ objectClasses.put(oc,ocName);
+ }
+ }
+ else if (attrType.isOperational())
+ {
+ List<Attribute> attrs = operationalAttributes.get(attrType);
+ if (attrs == null)
+ {
+ attrs = new ArrayList<Attribute>(1);
+ attrs.add(attr);
+ operationalAttributes.put(attrType, attrs);
+ }
+ else
+ {
+ attrs.add(attr);
+ }
+ }
+ else
+ {
+ List<Attribute> attrs = userAttributes.get(attrType);
+ if (attrs == null)
+ {
+ attrs = new ArrayList<Attribute>(1);
+ attrs.add(attr);
+ userAttributes.put(attrType, attrs);
+ }
+ else
+ {
+ // Check to see if any of the existing attributes in the list
+ // have the same set of options. If so, then add the values
+ // to that attribute.
+ boolean attributeSeen = false;
+ for (Attribute ea : attrs)
+ {
+ if (ea.optionsEqual(attr.getOptions()))
+ {
+ LinkedHashSet<AttributeValue> valueSet = ea.getValues();
+ valueSet.addAll(attr.getValues());
+ attributeSeen = true;
+ }
+ }
+ if (!attributeSeen)
+ {
+ // This is the first occurrence of the attribute and options.
+ attrs.add(attr);
+ }
+ }
+ }
+ }
+ catch (LDAPException le)
+ {
+ setResultCode(ResultCode.valueOf(le.getResultCode()));
+ appendErrorMessage(le.getMessage());
+
+ objectClasses = null;
+ userAttributes = null;
+ operationalAttributes = null;
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setAttribute(AttributeType attributeType,
+ List<Attribute> attributeList)
+ {
+ if (attributeType.isOperational())
+ {
+ if ((attributeList == null) || (attributeList.isEmpty()))
+ {
+ operationalAttributes.remove(attributeType);
+ }
+ else
+ {
+ operationalAttributes.put(attributeType, attributeList);
+ }
+ }
+ else
+ {
+ if ((attributeList == null) || (attributeList.isEmpty()))
+ {
+ userAttributes.remove(attributeType);
+ }
+ else
+ {
+ userAttributes.put(attributeType, attributeList);
+ }
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void removeAttribute(AttributeType attributeType)
+ {
+ if (attributeType.isOperational())
+ {
+ operationalAttributes.remove(attributeType);
+ }
+ else
+ {
+ userAttributes.remove(attributeType);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getChangeNumber()
+ {
+ return changeNumber;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setChangeNumber(long changeNumber)
+ {
+ this.changeNumber = changeNumber;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final OperationType getOperationType()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ return OperationType.ADD;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message,
+ int messageID)
+ {
+ // Before calling clientConnection.disconnect, we need to mark this
+ // operation as cancelled so that the attempt to cancel it later won't cause
+ // an unnecessary delay.
+ setCancelResult(CancelResult.CANCELED);
+
+ clientConnection.disconnect(disconnectReason, sendNotification, message,
+ messageID);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String[][] getRequestLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }
+ };
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String[][] getResponseLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ String resultCode = String.valueOf(getResultCode().getIntValue());
+
+ String errorMessage;
+ StringBuilder errorMessageBuffer = getErrorMessage();
+ if (errorMessageBuffer == null)
+ {
+ errorMessage = null;
+ }
+ else
+ {
+ errorMessage = errorMessageBuffer.toString();
+ }
+
+ String matchedDNStr;
+ DN matchedDN = getMatchedDN();
+ if (matchedDN == null)
+ {
+ matchedDNStr = null;
+ }
+ else
+ {
+ matchedDNStr = matchedDN.toString();
+ }
+
+ String referrals;
+ List<String> referralURLs = getReferralURLs();
+ if ((referralURLs == null) || referralURLs.isEmpty())
+ {
+ referrals = null;
+ }
+ else
+ {
+ StringBuilder buffer = new StringBuilder();
+ Iterator<String> iterator = referralURLs.iterator();
+ buffer.append(iterator.next());
+
+ while (iterator.hasNext())
+ {
+ buffer.append(", ");
+ buffer.append(iterator.next());
+ }
+
+ referrals = buffer.toString();
+ }
+
+ String processingTime =
+ String.valueOf(getProcessingTime());
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
+ new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
+ new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
+ new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
+ new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return proxiedAuthorizationDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ArrayList<Control> getResponseControls()
+ {
+ return responseControls;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void addResponseControl(Control control)
+ {
+ responseControls.add(control);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void removeResponseControl(Control control)
+ {
+ responseControls.remove(control);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final CancelResult cancel(CancelRequest cancelRequest)
+ {
+ this.cancelRequest = cancelRequest;
+
+ CancelResult cancelResult = getCancelResult();
+ long stopWaitingTime = System.currentTimeMillis() + 5000;
+ while ((cancelResult == null) &&
+ (System.currentTimeMillis() < stopWaitingTime))
+ {
+ try
+ {
+ Thread.sleep(50);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+
+ cancelResult = getCancelResult();
+ }
+
+ if (cancelResult == null)
+ {
+ // This can happen in some rare cases (e.g., if a client disconnects and
+ // there is still a lot of data to send to that client), and in this case
+ // we'll prevent the cancel thread from blocking for a long period of
+ // time.
+ cancelResult = CancelResult.CANNOT_CANCEL;
+ }
+
+ return cancelResult;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final CancelRequest getCancelRequest()
+ {
+ return cancelRequest;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public
+ boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ this.cancelRequest = cancelRequest;
+ return true;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void toString(StringBuilder buffer)
+ {
+ buffer.append("AddOperation(connID=");
+ buffer.append(clientConnection.getConnectionID());
+ buffer.append(", opID=");
+ buffer.append(operationID);
+ buffer.append(", dn=");
+ buffer.append(rawEntryDN);
+ buffer.append(")");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+ {
+ this.proxiedAuthorizationDN = proxiedAuthorizationDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void run()
+ {
+ // Start the processing timer.
+ setProcessingStartTime();
+ setResultCode(ResultCode.UNDEFINED);
+
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelRequest() != null)
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ return;
+ }
+
+
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+ // Create a labeled block of code that we can break out of if a problem is
+ // detected.
+ addProcessing:
+ {
+ // Invoke the pre-parse add plugins.
+ PreParsePluginResult preParseResult =
+ pluginConfigManager.invokePreParseAddPlugins(this);
+ if (preParseResult.connectionTerminated())
+ {
+ // There's no point in continuing with anything. Log the request and
+ // result and return.
+ setResultCode(ResultCode.CANCELED);
+
+ int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
+ appendErrorMessage(getMessage(msgID));
+
+ setProcessingStopTime();
+
+ logAddRequest(this);
+ logAddResponse(this);
+ pluginConfigManager.invokePostResponseAddPlugins(this);
+ return;
+ }
+ else if (preParseResult.sendResponseImmediately())
+ {
+ logAddRequest(this);
+ break addProcessing;
+ }
+ else if (preParseResult.skipCoreProcessing())
+ {
+ break addProcessing;
+ }
+
+ // Log the add request message.
+ logAddRequest(this);
+
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelRequest() != null)
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ logAddResponse(this);
+ pluginConfigManager.invokePostResponseAddPlugins(this);
+ return;
+ }
+
+
+ // Process the entry DN and set of attributes to convert them from their
+ // raw forms as provided by the client to the forms required for the rest
+ // of the add processing.
+ DN entryDN = getEntryDN();
+ if (entryDN == null){
+ break addProcessing;
+ }
+
+
+ // Retrieve the network group attached to the client connection
+ // and get a workflow to process the operation.
+ NetworkGroup ng = getClientConnection().getNetworkGroup();
+ Workflow workflow = ng.getWorkflowCandidate(entryDN);
+ if (workflow == null)
+ {
+ // We have found no workflow for the requested base DN, just return
+ // a no such entry result code and stop the processing.
+ updateOperationErrMsgAndResCode();
+ break addProcessing;
+ }
+ workflow.execute(this);
+ }
+
+ // Check for and handle a request to cancel this operation.
+ if ((getCancelRequest() != null) ||
+ (getCancelResult() == CancelResult.CANCELED))
+ {
+ if (getCancelRequest() != null){
+ indicateCancelled(getCancelRequest());
+ }
+ setProcessingStopTime();
+ logAddResponse(this);
+ invokePostResponsePlugins();
+ return;
+ }
+
+ // Indicate that it is now too late to attempt to cancel the operation.
+ setCancelResult(CancelResult.TOO_LATE);
+
+ // Stop the processing timer.
+ setProcessingStopTime();
+
+ // Send the add response to the client.
+ getClientConnection().sendResponse(this);
+
+ // Log the add response.
+ logAddResponse(this);
+
+ // Check wether there are local operations in attachments
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+ if (localOperations != null && (! localOperations.isEmpty())){
+ for (Object localOp : localOperations)
+ {
+ LocalBackendAddOperation localOperation =
+ (LocalBackendAddOperation)localOp;
+ // Notify any persistent searches that might be registered with the
+ // server.
+ if ((getResultCode() == ResultCode.SUCCESS) &&
+ (localOperation.getEntryToAdd() != null))
+ {
+ for (PersistentSearch persistentSearch :
+ DirectoryServer.getPersistentSearches())
+ {
+ try
+ {
+ persistentSearch.processAdd(localOperation,
+ localOperation.getEntryToAdd());
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ int msgID = MSGID_ADD_ERROR_NOTIFYING_PERSISTENT_SEARCH;
+ String message = getMessage(msgID,
+ String.valueOf(persistentSearch),
+ getExceptionMessage(e));
+ logError(ErrorLogCategory.CORE_SERVER,
+ ErrorLogSeverity.SEVERE_ERROR,
+ message, msgID);
+
+ DirectoryServer.deregisterPersistentSearch(persistentSearch);
+ }
+ }
+ }
+
+ // Invoke the post-response add plugins.
+ pluginConfigManager.invokePostResponseAddPlugins(localOperation);
+ }
+ }
+ }
+
+ /**
+ * Updates the error message and the result code of the operation.
+ *
+ * This method is called because no workflows were found to process
+ * the operation.
+ */
+ private void updateOperationErrMsgAndResCode()
+ {
+ DN entryDN = getEntryDN();
+ DN parentDN = entryDN.getParentDNInSuffix();
+ if (parentDN == null)
+ {
+ // Either this entry is a suffix or doesn't belong in the directory.
+ if (DirectoryServer.isNamingContext(entryDN))
+ {
+ // This is fine. This entry is one of the configured suffixes.
+ }
+ else if (entryDN.isNullDN())
+ {
+ // This is not fine. The root DSE cannot be added.
+ setResultCode(ResultCode.UNWILLING_TO_PERFORM);
+ appendErrorMessage(getMessage(MSGID_ADD_CANNOT_ADD_ROOT_DSE));
+ }
+ else
+ {
+ // The entry doesn't have a parent but isn't a suffix. This is not
+ // allowed.
+ setResultCode(ResultCode.NO_SUCH_OBJECT);
+ appendErrorMessage(getMessage(MSGID_ADD_ENTRY_NOT_SUFFIX,
+ String.valueOf(entryDN)));
+ }
+ }
+ }
+
+ /**
+ * Execute the postResponseAddPlugins.
+ */
+ private void invokePostResponsePlugins()
+ {
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+ // Check wether there are local operations in attachments
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+
+ if (localOperations != null && (! localOperations.isEmpty()))
+ {
+ for (Object localOp : localOperations)
+ {
+ LocalBackendAddOperation localOperation =
+ (LocalBackendAddOperation)localOp;
+ // Invoke the post-response add plugins.
+ pluginConfigManager.invokePostResponseAddPlugins(localOperation);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This method always returns null.
+ */
+ public Entry getEntryToAdd()
+ {
+ return null;
+ }
+
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/AddOperationWrapper.java b/opendj-sdk/opends/src/server/org/opends/server/core/AddOperationWrapper.java
new file mode 100644
index 0000000..7497bb6
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/AddOperationWrapper.java
@@ -0,0 +1,653 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.RawAttribute;
+import org.opends.server.types.ResultCode;
+
+/**
+ * This abstract class wraps/decorates a given add operation.
+ * This class will be extended by sub-classes to enhance the
+ * functionnality of the AddOperationBasis.
+ */
+public abstract class AddOperationWrapper implements AddOperation
+{
+ private AddOperation add;
+
+ /**
+ * Creates a new add operation based on the provided add operation.
+ *
+ * @param add The add operation to wrap
+ */
+ public AddOperationWrapper(AddOperation add){
+ this.add = add;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addObjectClass(ObjectClass objectClass, String name)
+ {
+ add.addObjectClass(objectClass, name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addRawAttribute(RawAttribute rawAttribute)
+ {
+ add.addRawAttribute(rawAttribute);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addRequestControl(Control control)
+ {
+ add.addRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addResponseControl(Control control)
+ {
+ add.addResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendAdditionalLogMessage(String message)
+ {
+ add.appendAdditionalLogMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendErrorMessage(String message)
+ {
+ add.appendErrorMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult cancel(CancelRequest cancelRequest)
+ {
+ return add.cancel(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message, int messageID)
+ {
+ add.disconnectClient(disconnectReason, sendNotification, message,
+ messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean dontSynchronize()
+ {
+ return add.dontSynchronize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getAdditionalLogMessage()
+ {
+ return add.getAdditionalLogMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getAttachment(String name)
+ {
+ return add.getAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<String, Object> getAttachments()
+ {
+ return add.getAttachments();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getAuthorizationDN()
+ {
+ return add.getAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry getAuthorizationEntry()
+ {
+ return add.getAuthorizationEntry();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelRequest getCancelRequest()
+ {
+ return add.getCancelRequest();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult getCancelResult()
+ {
+ return add.getCancelResult();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getChangeNumber()
+ {
+ return add.getChangeNumber();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClientConnection getClientConnection()
+ {
+ return add.getClientConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getCommonLogElements()
+ {
+ return add.getCommonLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getConnectionID()
+ {
+ return add.getConnectionID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getEntryDN()
+ {
+ return add.getEntryDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getErrorMessage()
+ {
+ return add.getErrorMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getMatchedDN()
+ {
+ return add.getMatchedDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMessageID()
+ {
+ return add.getMessageID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<ObjectClass, String> getObjectClasses()
+ {
+ return add.getObjectClasses();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<AttributeType, List<Attribute>> getOperationalAttributes()
+ {
+ return add.getOperationalAttributes();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getOperationID()
+ {
+ return add.getOperationID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public OperationType getOperationType()
+ {
+ return add.getOperationType();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStartTime()
+ {
+ return add.getProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStopTime()
+ {
+ return add.getProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingTime()
+ {
+ return add.getProcessingTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<RawAttribute> getRawAttributes()
+ {
+ return add.getRawAttributes();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString getRawEntryDN()
+ {
+ return add.getRawEntryDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<String> getReferralURLs()
+ {
+ return add.getReferralURLs();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getRequestControls()
+ {
+ return add.getRequestControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getRequestLogElements()
+ {
+ return add.getRequestLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getResponseControls()
+ {
+ return add.getResponseControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getResponseLogElements()
+ {
+ return add.getResponseLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultCode getResultCode()
+ {
+ return add.getResultCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<AttributeType, List<Attribute>> getUserAttributes()
+ {
+ return add.getUserAttributes();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void indicateCancelled(CancelRequest cancelRequest)
+ {
+ add.indicateCancelled(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isInternalOperation()
+ {
+ return add.isInternalOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSynchronizationOperation()
+ {
+ return add.isSynchronizationOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void operationCompleted()
+ {
+ add.operationCompleted();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object removeAttachment(String name)
+ {
+ return add.removeAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeAttribute(AttributeType attributeType)
+ {
+ add.removeAttribute(attributeType);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeObjectClass(ObjectClass objectClass)
+ {
+ add.removeObjectClass(objectClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeRequestControl(Control control)
+ {
+ add.removeRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeResponseControl(Control control)
+ {
+ add.removeResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAdditionalLogMessage(StringBuilder additionalLogMessage)
+ {
+ add.setAdditionalLogMessage(additionalLogMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object setAttachment(String name, Object value)
+ {
+ return add.setAttachment(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttachments(Map<String, Object> attachments)
+ {
+ add.setAttachments(attachments);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttribute(AttributeType attributeType,
+ List<Attribute> attributeList)
+ {
+ add.setAttribute(attributeType, attributeList);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAuthorizationEntry(Entry authorizationEntry)
+ {
+ add.setAuthorizationEntry(authorizationEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ return add.setCancelRequest(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCancelResult(CancelResult cancelResult)
+ {
+ add.setCancelResult(cancelResult);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setChangeNumber(long changeNumber)
+ {
+ add.setChangeNumber(changeNumber);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDontSynchronize(boolean dontSynchronize)
+ {
+ add.setDontSynchronize(dontSynchronize);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setErrorMessage(StringBuilder errorMessage)
+ {
+ add.setErrorMessage(errorMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInternalOperation(boolean isInternalOperation)
+ {
+ add.setInternalOperation(isInternalOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMatchedDN(DN matchedDN)
+ {
+ add.setMatchedDN(matchedDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStartTime()
+ {
+ add.setProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStopTime()
+ {
+ add.setProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawAttributes(List<RawAttribute> rawAttributes)
+ {
+ add.setRawAttributes(rawAttributes);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawEntryDN(ByteString rawEntryDN)
+ {
+ add.setRawEntryDN(rawEntryDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setReferralURLs(List<String> referralURLs)
+ {
+ add.setReferralURLs(referralURLs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResponseData(DirectoryException directoryException)
+ {
+ add.setResponseData(directoryException);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResultCode(ResultCode resultCode)
+ {
+ add.setResultCode(resultCode);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSynchronizationOperation(boolean isSynchronizationOperation)
+ {
+ add.setSynchronizationOperation(isSynchronizationOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return add.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void toString(StringBuilder buffer)
+ {
+ add.toString(buffer);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return add.getProxiedAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+ {
+ add.setProxiedAuthorizationDN(proxiedAuthorizationDN);
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/BindOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/BindOperation.java
index a62bff4..03cf58b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/BindOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/BindOperation.java
@@ -26,414 +26,33 @@
*/
package org.opends.server.core;
-
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.concurrent.locks.Lock;
-
-import org.opends.server.api.ClientConnection;
-import org.opends.server.api.SASLMechanismHandler;
-import org.opends.server.api.plugin.PostOperationPluginResult;
-import org.opends.server.api.plugin.PreOperationPluginResult;
-import org.opends.server.api.plugin.PreParsePluginResult;
-import org.opends.server.controls.AuthorizationIdentityResponseControl;
-import org.opends.server.controls.PasswordExpiredControl;
-import org.opends.server.controls.PasswordExpiringControl;
-import org.opends.server.controls.PasswordPolicyErrorType;
-import org.opends.server.controls.PasswordPolicyResponseControl;
-import org.opends.server.controls.PasswordPolicyWarningType;
import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.types.AccountStatusNotificationType;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.AuthenticationType;
import org.opends.server.types.ByteString;
-import org.opends.server.types.CancelRequest;
-import org.opends.server.types.CancelResult;
-import org.opends.server.types.Control;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.LockManager;
import org.opends.server.types.Operation;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.operation.PostOperationBindOperation;
-import org.opends.server.types.operation.PostResponseBindOperation;
-import org.opends.server.types.operation.PreOperationBindOperation;
-import org.opends.server.types.operation.PreParseBindOperation;
-
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.core.CoreConstants.*;
-import static org.opends.server.loggers.AccessLogger.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.messages.CoreMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
-
-
/**
- * This class defines an operation that may be used to authenticate a user to
- * the Directory Server. Note that for security restrictions, response messages
- * that may be returned to the client must be carefully cleaned to ensure that
- * they do not provide a malicious client with information that may be useful in
- * an attack. This does impact the debugability of the server, but that can
- * be addressed by calling the <CODE>setAuthFailureReason</CODE> method, which
- * can provide a reason for a failure in a form that will not be returned to the
- * client but may be written to a log file.
+ * This interface defines an operation that may be used to authenticate a user
+ * to the Directory Server. Note that for security restrictions, response
+ * messages that may be returned to the client must be carefully cleaned to
+ * ensure that they do not provide a malicious client with information that may
+ * be useful in an attack. This does impact the debugability of the server,
+ * but that can be addressed by calling the <CODE>setAuthFailureReason</CODE>
+ * method, which can provide a reason for a failure in a form that will not be
+ * returned to the client but may be written to a log file.
*/
-public class BindOperation
- extends Operation
- implements PreParseBindOperation, PreOperationBindOperation,
- PostOperationBindOperation, PostResponseBindOperation
+public interface BindOperation extends Operation
{
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- // The credentials used for SASL authentication.
- private ASN1OctetString saslCredentials;
-
- // The server SASL credentials provided to the client in the response.
- private ASN1OctetString serverSASLCredentials;
-
- // The authentication info for this bind operation.
- private AuthenticationInfo authInfo;
-
- // The authentication type used for this bind operation.
- private AuthenticationType authType;
-
- // Indicates whether the warning notification that should be sent to the user
- // would be the first warning.
- private boolean isFirstWarning;
-
- // Indicates whether the authentication should use a grace login if it is
- // successful.
- private boolean isGraceLogin;
-
- // Indicates whether the user's password must be changed before any other
- // operations will be allowed.
- private boolean mustChangePassword;
-
- // Indicates whether the client included the password policy control in the
- // bind request.
- private boolean pwPolicyControlRequested;
-
- // The raw, unprocessed bind DN as contained in the client request.
- private ByteString rawBindDN;
-
- // The password used for simple authentication.
- private ByteString simplePassword;
-
- // The bind DN used for this bind operation.
- private DN bindDN;
-
- // The DN of the user entry that is attempting to authenticate.
- private DN userEntryDN;
-
- // The entry of the user that successfully authenticated during processing of
- // this bind operation.
- private Entry authenticatedUserEntry;
-
- // The DN of the user as whom a SASL authentication was attempted (regardless
- // of whether the authentication was successful) for the purpose of updating
- // password policy state information.
- private Entry saslAuthUserEntry;
-
- // The unique ID associated with the failure reason message.
- private int authFailureID;
-
- // The password policy warning value that should be included in the response
- // control.
- private int pwPolicyWarningValue;
-
- // The set of response controls for this bind operation.
- private List<Control> responseControls;
-
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
- // The password policy error type that should be included in the response
- // control
- private PasswordPolicyErrorType pwPolicyErrorType;
-
- // The password policy warning type that should be included in the response
- // control
- private PasswordPolicyWarningType pwPolicyWarningType;
-
- // The password policy state information for this bind operation.
- private PasswordPolicyState pwPolicyState;
-
- // A message explaining the reason for the authentication failure.
- private String authFailureReason;
-
- // A string representation of the protocol version for this bind operation.
- private String protocolVersion;
-
- // The SASL mechanism used for SASL authentication.
- private String saslMechanism;
-
-
-
- /**
- * Creates a new simple bind operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param protocolVersion The string representation of the protocol version
- * associated with this bind request.
- * @param rawBindDN The raw, unprocessed bind DN as provided in the
- * request from the client.
- * @param simplePassword The password to use for the simple
- * authentication.
- */
- public BindOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- String protocolVersion, ByteString rawBindDN,
- ByteString simplePassword)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.protocolVersion = protocolVersion;
- this.authType = AuthenticationType.SIMPLE;
- this.saslMechanism = null;
- this.saslCredentials = null;
-
- if (rawBindDN == null)
- {
- this.rawBindDN = new ASN1OctetString();
- }
- else
- {
- this.rawBindDN = rawBindDN;
- }
-
- if (simplePassword == null)
- {
- this.simplePassword = new ASN1OctetString();
- }
- else
- {
- this.simplePassword = simplePassword;
- }
-
- bindDN = null;
- userEntryDN = null;
- responseControls = new ArrayList<Control>(0);
- authFailureID = 0;
- authFailureReason = null;
- authenticatedUserEntry = null;
- saslAuthUserEntry = null;
- isFirstWarning = false;
- isGraceLogin = false;
- mustChangePassword = false;
- pwPolicyControlRequested = false;
- pwPolicyErrorType = null;
- pwPolicyWarningType = null;
- pwPolicyWarningValue = -1;
- }
-
-
-
- /**
- * Creates a new SASL bind operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param protocolVersion The string representation of the protocol version
- * associated with this bind request.
- * @param rawBindDN The raw, unprocessed bind DN as provided in the
- * request from the client.
- * @param saslMechanism The SASL mechanism included in the request.
- * @param saslCredentials The optional SASL credentials included in the
- * request.
- */
- public BindOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- String protocolVersion, ByteString rawBindDN,
- String saslMechanism, ASN1OctetString saslCredentials)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.protocolVersion = protocolVersion;
- this.authType = AuthenticationType.SASL;
- this.saslMechanism = saslMechanism;
- this.saslCredentials = saslCredentials;
- this.simplePassword = null;
-
- if (rawBindDN == null)
- {
- this.rawBindDN = new ASN1OctetString();
- }
- else
- {
- this.rawBindDN = rawBindDN;
- }
-
- bindDN = null;
- userEntryDN = null;
- responseControls = new ArrayList<Control>(0);
- authFailureID = 0;
- authFailureReason = null;
- authenticatedUserEntry = null;
- saslAuthUserEntry = null;
- }
-
-
-
- /**
- * Creates a new simple bind operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param protocolVersion The string representation of the protocol version
- * associated with this bind request.
- * @param bindDN The bind DN for this bind operation.
- * @param simplePassword The password to use for the simple
- * authentication.
- */
- public BindOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- String protocolVersion, DN bindDN,
- ByteString simplePassword)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.protocolVersion = protocolVersion;
- this.authType = AuthenticationType.SIMPLE;
- this.bindDN = bindDN;
- this.saslMechanism = null;
- this.saslCredentials = null;
-
- if (bindDN == null)
- {
- rawBindDN = new ASN1OctetString();
- }
- else
- {
- rawBindDN = new ASN1OctetString(bindDN.toString());
- }
-
- if (simplePassword == null)
- {
- this.simplePassword = new ASN1OctetString();
- }
- else
- {
- this.simplePassword = simplePassword;
- }
-
- responseControls = new ArrayList<Control>(0);
- authFailureID = 0;
- authFailureReason = null;
- authenticatedUserEntry = null;
- saslAuthUserEntry = null;
- isFirstWarning = false;
- isGraceLogin = false;
- mustChangePassword = false;
- pwPolicyControlRequested = false;
- pwPolicyErrorType = null;
- pwPolicyWarningType = null;
- pwPolicyWarningValue = -1;
- userEntryDN = null;
- }
-
-
-
- /**
- * Creates a new SASL bind operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param protocolVersion The string representation of the protocol version
- * associated with this bind request.
- * @param bindDN The bind DN for this bind operation.
- * @param saslMechanism The SASL mechanism included in the request.
- * @param saslCredentials The optional SASL credentials included in the
- * request.
- */
- public BindOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- String protocolVersion, DN bindDN,
- String saslMechanism, ASN1OctetString saslCredentials)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.protocolVersion = protocolVersion;
- this.authType = AuthenticationType.SASL;
- this.bindDN = bindDN;
- this.saslMechanism = saslMechanism;
- this.saslCredentials = saslCredentials;
- this.simplePassword = null;
-
- if (bindDN == null)
- {
- rawBindDN = new ASN1OctetString();
- }
- else
- {
- rawBindDN = new ASN1OctetString(bindDN.toString());
- }
-
- responseControls = new ArrayList<Control>(0);
- authFailureID = 0;
- authFailureReason = null;
- authenticatedUserEntry = null;
- saslAuthUserEntry = null;
- userEntryDN = null;
- }
-
-
/**
* Retrieves the authentication type for this bind operation.
*
* @return The authentication type for this bind operation.
*/
- public final AuthenticationType getAuthenticationType()
- {
- return authType;
- }
-
-
+ public abstract AuthenticationType getAuthenticationType();
/**
* Retrieves the raw, unprocessed bind DN for this bind operation as contained
@@ -443,12 +62,7 @@
* @return The raw, unprocessed bind DN for this bind operation as contained
* in the client request.
*/
- public final ByteString getRawBindDN()
- {
- return rawBindDN;
- }
-
-
+ public abstract ByteString getRawBindDN();
/**
* Specifies the raw, unprocessed bind DN for this bind operation. This
@@ -456,21 +70,7 @@
*
* @param rawBindDN The raw, unprocessed bind DN for this bind operation.
*/
- public final void setRawBindDN(ByteString rawBindDN)
- {
- if (rawBindDN == null)
- {
- this.rawBindDN = new ASN1OctetString();
- }
- else
- {
- this.rawBindDN = rawBindDN;
- }
-
- bindDN = null;
- }
-
-
+ public abstract void setRawBindDN(ByteString rawBindDN);
/**
* Retrieves a string representation of the protocol version associated with
@@ -479,12 +79,7 @@
* @return A string representation of the protocol version associated with
* this bind request.
*/
- public String getProtocolVersion()
- {
- return protocolVersion;
- }
-
-
+ public String getProtocolVersion();
/**
* Specifies the string representation of the protocol version associated with
@@ -493,12 +88,7 @@
* @param protocolVersion The string representation of the protocol version
* associated with this bind request.
*/
- public void setProtocolVersion(String protocolVersion)
- {
- this.protocolVersion = protocolVersion;
- }
-
-
+ public void setProtocolVersion(String protocolVersion);
/**
* Retrieves the bind DN for this bind operation. This method should not be
@@ -509,24 +99,14 @@
* @return The bind DN for this bind operation, or <CODE>null</CODE> if the
* raw DN has not yet been processed.
*/
- public final DN getBindDN()
- {
- return bindDN;
- }
-
-
+ public abstract DN getBindDN();
/**
* Retrieves the simple authentication password for this bind operation.
*
* @return The simple authentication password for this bind operation.
*/
- public final ByteString getSimplePassword()
- {
- return simplePassword;
- }
-
-
+ public abstract ByteString getSimplePassword();
/**
* Specifies the simple authentication password for this bind operation.
@@ -534,23 +114,7 @@
* @param simplePassword The simple authentication password for this bind
* operation.
*/
- public final void setSimplePassword(ByteString simplePassword)
- {
- if (simplePassword == null)
- {
- this.simplePassword = new ASN1OctetString();
- }
- else
- {
- this.simplePassword = simplePassword;
- }
-
- authType = AuthenticationType.SIMPLE;
- saslMechanism = null;
- saslCredentials = null;
- }
-
-
+ public abstract void setSimplePassword(ByteString simplePassword);
/**
* Retrieves the SASL mechanism for this bind operation.
@@ -558,12 +122,7 @@
* @return The SASL mechanism for this bind operation, or <CODE>null</CODE>
* if the bind does not use SASL authentication.
*/
- public final String getSASLMechanism()
- {
- return saslMechanism;
- }
-
-
+ public abstract String getSASLMechanism();
/**
* Retrieves the SASL credentials for this bind operation.
@@ -571,12 +130,7 @@
* @return The SASL credentials for this bind operation, or <CODE>null</CODE>
* if there are none or if the bind does not use SASL authentication.
*/
- public final ASN1OctetString getSASLCredentials()
- {
- return saslCredentials;
- }
-
-
+ public abstract ASN1OctetString getSASLCredentials();
/**
* Specifies the SASL credentials for this bind operation.
@@ -585,17 +139,8 @@
* @param saslCredentials The SASL credentials for this bind operation, or
* <CODE>null</CODE> if there are none.
*/
- public final void setSASLCredentials(String saslMechanism,
- ASN1OctetString saslCredentials)
- {
- this.saslMechanism = saslMechanism;
- this.saslCredentials = saslCredentials;
-
- authType = AuthenticationType.SASL;
- simplePassword = null;
- }
-
-
+ public abstract void setSASLCredentials(String saslMechanism,
+ ASN1OctetString saslCredentials);
/**
* Retrieves the set of server SASL credentials to include in the bind
@@ -604,12 +149,7 @@
* @return The set of server SASL credentials to include in the bind
* response, or <CODE>null</CODE> if there are none.
*/
- public final ASN1OctetString getServerSASLCredentials()
- {
- return serverSASLCredentials;
- }
-
-
+ public abstract ASN1OctetString getServerSASLCredentials();
/**
* Specifies the set of server SASL credentials to include in the bind
@@ -618,13 +158,8 @@
* @param serverSASLCredentials The set of server SASL credentials to
* include in the bind response.
*/
- public final void setServerSASLCredentials(ASN1OctetString
- serverSASLCredentials)
- {
- this.serverSASLCredentials = serverSASLCredentials;
- }
-
-
+ public abstract void setServerSASLCredentials(
+ ASN1OctetString serverSASLCredentials);
/**
* Retrieves the user entry associated with the SASL authentication attempt.
@@ -636,12 +171,7 @@
* <CODE>null</CODE> if it was not a SASL authentication or the SASL
* processing was not able to map the request to a user.
*/
- public final Entry getSASLAuthUserEntry()
- {
- return saslAuthUserEntry;
- }
-
-
+ public abstract Entry getSASLAuthUserEntry();
/**
* Specifies the user entry associated with the SASL authentication attempt.
@@ -652,12 +182,7 @@
* @param saslAuthUserEntry The user entry associated with the SASL
* authentication attempt.
*/
- public final void setSASLAuthUserEntry(Entry saslAuthUserEntry)
- {
- this.saslAuthUserEntry = saslAuthUserEntry;
- }
-
-
+ public abstract void setSASLAuthUserEntry(Entry saslAuthUserEntry);
/**
* Retrieves a human-readable message providing the reason that the
@@ -666,12 +191,7 @@
* @return A human-readable message providing the reason that the
* authentication failed, or <CODE>null</CODE> if none is available.
*/
- public final String getAuthFailureReason()
- {
- return authFailureReason;
- }
-
-
+ public abstract String getAuthFailureReason();
/**
* Retrieves the unique identifier for the authentication failure reason, if
@@ -680,12 +200,7 @@
* @return The unique identifier for the authentication failure reason, or
* zero if none is available.
*/
- public final int getAuthFailureID()
- {
- return authFailureID;
- }
-
-
+ public abstract int getAuthFailureID();
/**
* Specifies the reason that the authentication failed.
@@ -695,21 +210,7 @@
* @param reason A human-readable message providing the reason that the
* authentication failed.
*/
- public final void setAuthFailureReason(int id, String reason)
- {
- if (id < 0)
- {
- authFailureID = 0;
- }
- else
- {
- authFailureID = id;
- }
-
- authFailureReason = reason;
- }
-
-
+ public abstract void setAuthFailureReason(int id, String reason);
/**
* Retrieves the user entry DN for this bind operation. It will only be
@@ -720,12 +221,7 @@
* the bind processing has not progressed far enough to identify the
* user or if the user DN could not be determined.
*/
- public final DN getUserEntryDN()
- {
- return userEntryDN;
- }
-
-
+ public abstract DN getUserEntryDN();
/**
* Retrieves the authentication info that resulted from processing this bind
@@ -734,12 +230,7 @@
* @return The authentication info that resulted from processing this bind
* operation.
*/
- public final AuthenticationInfo getAuthenticationInfo()
- {
- return authInfo;
- }
-
-
+ public abstract AuthenticationInfo getAuthenticationInfo();
/**
* Specifies the authentication info that resulted from processing this bind
@@ -749,1674 +240,17 @@
* @param authInfo The authentication info that resulted from processing
* this bind operation.
*/
- public final void setAuthenticationInfo(AuthenticationInfo authInfo)
- {
- this.authInfo = authInfo;
- }
-
-
+ public abstract void setAuthenticationInfo(AuthenticationInfo authInfo);
/**
- * {@inheritDoc}
+ * Set the user entry DN for this bind operation.
+ *
+ * @param userEntryDN The user entry DN for this bind operation, or
+ * <CODE>null</CODE> if the bind processing has not
+ * progressed far enough to identify the user or if
+ * the user DN could not be determined.
*/
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final OperationType getOperationType()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- return OperationType.BIND;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void disconnectClient(DisconnectReason disconnectReason,
- boolean sendNotification, String message,
- int messageID)
- {
- // Since bind operations can't be cancelled, we don't need to do anything
- // but forward the request on to the client connection.
- clientConnection.disconnect(disconnectReason, sendNotification, message,
- messageID);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final String[][] getRequestLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- if (authType == AuthenticationType.SASL)
- {
- return new String[][]
- {
- new String[] { LOG_ELEMENT_BIND_DN, String.valueOf(rawBindDN) },
- new String[] { LOG_ELEMENT_AUTH_TYPE, authType.toString() },
- new String[] { LOG_ELEMENT_SASL_MECHANISM, saslMechanism }
- };
- }
- else
- {
- return new String[][]
- {
- new String[] { LOG_ELEMENT_BIND_DN, String.valueOf(rawBindDN) },
- new String[] { LOG_ELEMENT_AUTH_TYPE, authType.toString() }
- };
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final String[][] getResponseLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- String resultCode = String.valueOf(getResultCode().getIntValue());
-
- String errorMessage;
- StringBuilder errorMessageBuffer = getErrorMessage();
- if (errorMessageBuffer == null)
- {
- errorMessage = null;
- }
- else
- {
- errorMessage = errorMessageBuffer.toString();
- }
-
- String matchedDNStr;
- DN matchedDN = getMatchedDN();
- if (matchedDN == null)
- {
- matchedDNStr = null;
- }
- else
- {
- matchedDNStr = matchedDN.toString();
- }
-
- String referrals;
- List<String> referralURLs = getReferralURLs();
- if ((referralURLs == null) || referralURLs.isEmpty())
- {
- referrals = null;
- }
- else
- {
- StringBuilder buffer = new StringBuilder();
- Iterator<String> iterator = referralURLs.iterator();
- buffer.append(iterator.next());
-
- while (iterator.hasNext())
- {
- buffer.append(", ");
- buffer.append(iterator.next());
- }
-
- referrals = buffer.toString();
- }
-
- String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
-
- return new String[][]
- {
- new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
- new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
- new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
- new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
- new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
- };
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final List<Control> getResponseControls()
- {
- return responseControls;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void addResponseControl(Control control)
- {
- responseControls.add(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void removeResponseControl(Control control)
- {
- responseControls.remove(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void run()
- {
- // Start the processing timer and initially set the result to indicate that
- // the result is unknown.
- processingStartTime = System.currentTimeMillis();
- setResultCode(ResultCode.UNDEFINED);
- boolean returnAuthzID = false;
- int sizeLimit = DirectoryServer.getSizeLimit();
- int timeLimit = DirectoryServer.getTimeLimit();
- int lookthroughLimit = DirectoryServer.getLookthroughLimit();
-
-
- // Set a flag to indicate that a bind operation is in progress. This should
- // ensure that no new operations will be accepted for this client until the
- // bind is complete.
- clientConnection.setBindInProgress(true);
-
-
- // Wipe out any existing authentication for the client connection and create
- // a placeholder that will be used if the bind is successful.
- clientConnection.setUnauthenticated();
- authInfo = null;
-
-
- // Abandon any operations that may be in progress for the client.
- String cancelReason = getMessage(MSGID_CANCELED_BY_BIND_REQUEST);
- CancelRequest cancelRequest = new CancelRequest(true, cancelReason);
- clientConnection.cancelAllOperationsExcept(cancelRequest, getMessageID());
-
-
- // Get the plugin config manager that will be used for invoking plugins.
- PluginConfigManager pluginConfigManager =
- DirectoryServer.getPluginConfigManager();
- boolean skipPostOperation = false;
-
-
- // Create a labeled block of code that we can break out of if a problem is
- // detected.
-bindProcessing:
- {
- // Invoke the pre-parse bind plugins.
- PreParsePluginResult preParseResult =
- pluginConfigManager.invokePreParseBindPlugins(this);
- if (preParseResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the request and
- // result and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logBindRequest(this);
- logBindResponse(this);
- pluginConfigManager.invokePostResponseBindPlugins(this);
- return;
- }
- else if (preParseResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- logBindRequest(this);
- break bindProcessing;
- }
- else if (preParseResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break bindProcessing;
- }
-
-
- // Log the bind request message.
- logBindRequest(this);
-
-
- // Process the bind DN to convert it from the raw form as provided by the
- // client into the form required for the rest of the bind processing.
- try
- {
- if (bindDN == null)
- {
- bindDN = DN.decode(rawBindDN);
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(de.getMessageID(), de.getErrorMessage());
- break bindProcessing;
- }
-
- // Check to see if the client has permission to perform the
- // bind.
-
- // FIXME: for now assume that this will check all permission
- // pertinent to the operation. This includes any controls
- // specified.
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isAllowed(this) == false) {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- int msgID = MSGID_BIND_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- String message = getMessage(msgID, String.valueOf(bindDN));
- setAuthFailureReason(msgID, message);
-
- skipPostOperation = true;
- break bindProcessing;
- }
-
- // Check to see if there are any controls in the request. If so, then see
- // if there is any special processing required.
- List<Control> requestControls = getRequestControls();
- if ((requestControls != null) && (! requestControls.isEmpty()))
- {
- for (int i=0; i < requestControls.size(); i++)
- {
- Control c = requestControls.get(i);
- String oid = c.getOID();
-
- if (oid.equals(OID_AUTHZID_REQUEST))
- {
- returnAuthzID = true;
- }
- else if (oid.equals(OID_PASSWORD_POLICY_CONTROL))
- {
- pwPolicyControlRequested = true;
- }
-
- // NYI -- Add support for additional controls.
- else if (c.isCritical())
- {
- setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
-
- int msgID = MSGID_BIND_UNSUPPORTED_CRITICAL_CONTROL;
- appendErrorMessage(getMessage(msgID, String.valueOf(oid)));
-
- break bindProcessing;
- }
- }
- }
-
-
- // Check to see if this is a simple bind or a SASL bind and process
- // accordingly.
- switch (authType)
- {
- case SIMPLE:
- // See if this is an anonymous bind. If so, then determine whether
- // to allow it.
- if ((simplePassword == null) || (simplePassword.value().length == 0))
- {
- // If the server is in lockdown mode, then fail.
- if (DirectoryServer.lockdownMode())
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- int msgID = MSGID_BIND_REJECTED_LOCKDOWN_MODE;
- setAuthFailureReason(msgID, getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
- logBindResponse(this);
- break bindProcessing;
- }
-
- // If there is a bind DN, then see whether that is acceptable.
- if (DirectoryServer.bindWithDNRequiresPassword() &&
- ((bindDN != null) && (! bindDN.isNullDN())))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_BIND_DN_BUT_NO_PASSWORD;
- String message = getMessage(msgID);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
-
-
- // Invoke the pre-operation bind plugins.
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationBindPlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result
- // and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logBindResponse(this);
- pluginConfigManager.invokePostResponseBindPlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break bindProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break bindProcessing;
- }
-
- setResultCode(ResultCode.SUCCESS);
- authInfo = new AuthenticationInfo();
- break bindProcessing;
- }
-
-
- // See if the bind DN is actually one of the alternate root DNs
- // defined in the server. If so, then replace it with the actual DN
- // for that user.
- DN actualRootDN = DirectoryServer.getActualRootBindDN(bindDN);
- if (actualRootDN != null)
- {
- bindDN = actualRootDN;
- }
-
-
- // Get the user entry based on the bind DN. If it does not exist,
- // then fail.
- Lock userLock = null;
- for (int i=0; i < 3; i++)
- {
- userLock = LockManager.lockRead(bindDN);
- if (userLock != null)
- {
- break;
- }
- }
-
- if (userLock == null)
- {
- int msgID = MSGID_BIND_OPERATION_CANNOT_LOCK_USER;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(DirectoryServer.getServerErrorResultCode());
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
-
- try
- {
- Entry userEntry;
- try
- {
- userEntry = DirectoryServer.getEntry(bindDN);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(de.getMessageID(),
- de.getErrorMessage());
-
- userEntry = null;
- break bindProcessing;
- }
-
- if (userEntry == null)
- {
-
- int msgID = MSGID_BIND_OPERATION_UNKNOWN_USER;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
- else
- {
- userEntryDN = userEntry.getDN();
- }
-
-
- // Check to see if the user has a password. If not, then fail.
- // FIXME -- We need to have a way to enable/disable debugging.
- pwPolicyState = new PasswordPolicyState(userEntry, false, false);
- AttributeType pwType
- = pwPolicyState.getPolicy().getPasswordAttribute();
-
- List<Attribute> pwAttr = userEntry.getAttribute(pwType);
- if ((pwAttr == null) || (pwAttr.isEmpty()))
- {
- int msgID = MSGID_BIND_OPERATION_NO_PASSWORD;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
-
-
- // Check to see if the authentication must be done in a secure
- // manner. If so, then the client connection must be secure.
- if (pwPolicyState.getPolicy().requireSecureAuthentication() &&
- (! clientConnection.isSecure()))
- {
- int msgID = MSGID_BIND_OPERATION_INSECURE_SIMPLE_BIND;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
-
-
- // Check to see if the user is administratively disabled or locked.
- if (pwPolicyState.isDisabled())
- {
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_DISABLED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
- else if (pwPolicyState.isAccountExpired())
- {
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_EXPIRED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_EXPIRED, bindDN, msgID,
- message);
-
- break bindProcessing;
- }
- else if (pwPolicyState.lockedDueToFailures())
- {
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_FAILURE_LOCKED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
- }
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
- else if (pwPolicyState.lockedDueToMaximumResetAge())
- {
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_RESET_LOCKED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
- }
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_RESET_LOCKED, bindDN,
- msgID, message);
-
- break bindProcessing;
- }
- else if (pwPolicyState.lockedDueToIdleInterval())
- {
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_IDLE_LOCKED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
- }
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED, bindDN,
- msgID, message);
-
- break bindProcessing;
- }
-
-
- // Determine whether the password is expired, or whether the user
- // should be warned about an upcoming expiration.
- if (pwPolicyState.isPasswordExpired())
- {
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_EXPIRED;
- }
-
- int maxGraceLogins
- = pwPolicyState.getPolicy().getGraceLoginCount();
- if ((maxGraceLogins > 0) && pwPolicyState.mayUseGraceLogin())
- {
- List<Long> graceLoginTimes = pwPolicyState.getGraceLoginTimes();
- if ((graceLoginTimes == null) ||
- (graceLoginTimes.size() < maxGraceLogins))
- {
- isGraceLogin = true;
- mustChangePassword = true;
-
- if (pwPolicyWarningType == null)
- {
- pwPolicyWarningType =
- PasswordPolicyWarningType.GRACE_LOGINS_REMAINING;
- pwPolicyWarningValue = maxGraceLogins -
- (graceLoginTimes.size() + 1);
- }
- }
- else
- {
- int msgID = MSGID_BIND_OPERATION_PASSWORD_EXPIRED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.PASSWORD_EXPIRED, bindDN,
- msgID, message);
-
- break bindProcessing;
- }
- }
- else
- {
- int msgID = MSGID_BIND_OPERATION_PASSWORD_EXPIRED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.PASSWORD_EXPIRED, bindDN,
- msgID, message);
-
- break bindProcessing;
- }
- }
- else if (pwPolicyState.shouldWarn())
- {
- int numSeconds = pwPolicyState.getSecondsUntilExpiration();
- String timeToExpiration = secondsToTimeString(numSeconds);
-
- int msgID = MSGID_BIND_PASSWORD_EXPIRING;
- String message = getMessage(msgID, timeToExpiration);
- appendErrorMessage(message);
-
- if (pwPolicyWarningType == null)
- {
- pwPolicyWarningType =
- PasswordPolicyWarningType.TIME_BEFORE_EXPIRATION;
- pwPolicyWarningValue = numSeconds;
- }
-
- isFirstWarning = pwPolicyState.isFirstWarning();
- }
-
-
- // Check to see if the user's password has been reset.
- if (pwPolicyState.mustChangePassword())
- {
- mustChangePassword = true;
-
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.CHANGE_AFTER_RESET;
- }
- }
-
-
- // Invoke the pre-operation bind plugins.
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationBindPlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result
- // and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logBindResponse(this);
- pluginConfigManager.invokePostResponseBindPlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break bindProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break bindProcessing;
- }
-
-
- // Determine whether the provided password matches any of the stored
- // passwords for the user.
- if (pwPolicyState.passwordMatches(simplePassword))
- {
- setResultCode(ResultCode.SUCCESS);
-
- boolean isRoot = DirectoryServer.isRootDN(userEntry.getDN());
- if (DirectoryServer.lockdownMode() && (! isRoot))
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- int msgID = MSGID_BIND_REJECTED_LOCKDOWN_MODE;
- setAuthFailureReason(msgID, getMessage(msgID));
-
- break bindProcessing;
- }
-
- authInfo = new AuthenticationInfo(userEntry, simplePassword,
- isRoot);
-
-
- // See if the user's entry contains a custom size limit.
- AttributeType attrType =
- DirectoryServer.getAttributeType(OP_ATTR_USER_SIZE_LIMIT,
- true);
- List<Attribute> attrList = userEntry.getAttribute(attrType);
- if ((attrList != null) && (attrList.size() == 1))
- {
- Attribute a = attrList.get(0);
- LinkedHashSet<AttributeValue> values = a.getValues();
- Iterator<AttributeValue> iterator = values.iterator();
- if (iterator.hasNext())
- {
- AttributeValue v = iterator.next();
- if (iterator.hasNext())
- {
- int msgID = MSGID_BIND_MULTIPLE_USER_SIZE_LIMITS;
- String message =
- getMessage(msgID, String.valueOf(userEntry.getDN()));
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- else
- {
- try
- {
- sizeLimit = Integer.parseInt(v.getStringValue());
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_BIND_CANNOT_PROCESS_USER_SIZE_LIMIT;
- String message =
- getMessage(msgID, v.getStringValue(),
- String.valueOf(userEntry.getDN()));
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- }
- }
- }
-
-
- // See if the user's entry contains a custom time limit.
- attrType =
- DirectoryServer.getAttributeType(OP_ATTR_USER_TIME_LIMIT,
- true);
- attrList = userEntry.getAttribute(attrType);
- if ((attrList != null) && (attrList.size() == 1))
- {
- Attribute a = attrList.get(0);
- LinkedHashSet<AttributeValue> values = a.getValues();
- Iterator<AttributeValue> iterator = values.iterator();
- if (iterator.hasNext())
- {
- AttributeValue v = iterator.next();
- if (iterator.hasNext())
- {
- int msgID = MSGID_BIND_MULTIPLE_USER_TIME_LIMITS;
- String message =
- getMessage(msgID, String.valueOf(userEntry.getDN()));
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- else
- {
- try
- {
- timeLimit = Integer.parseInt(v.getStringValue());
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_BIND_CANNOT_PROCESS_USER_TIME_LIMIT;
- String message =
- getMessage(msgID, v.getStringValue(),
- String.valueOf(userEntry.getDN()));
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- }
- }
- }
-
-
- // See if the user's entry contains a custom lookthrough limit.
- attrType =
- DirectoryServer.getAttributeType(
- OP_ATTR_USER_LOOKTHROUGH_LIMIT, true);
- attrList = userEntry.getAttribute(attrType);
- if ((attrList != null) && (attrList.size() == 1))
- {
- Attribute a = attrList.get(0);
- LinkedHashSet<AttributeValue> values = a.getValues();
- Iterator<AttributeValue> iterator = values.iterator();
- if (iterator.hasNext())
- {
- AttributeValue v = iterator.next();
- if (iterator.hasNext())
- {
- int msgID = MSGID_BIND_MULTIPLE_USER_LOOKTHROUGH_LIMITS;
- String message =
- getMessage(msgID, String.valueOf(userEntry.getDN()));
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- else
- {
- try
- {
- lookthroughLimit = Integer.parseInt(v.getStringValue());
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID =
- MSGID_BIND_CANNOT_PROCESS_USER_LOOKTHROUGH_LIMIT;
- String message =
- getMessage(msgID, v.getStringValue(),
- String.valueOf(userEntry.getDN()));
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- }
- }
- }
-
-
- pwPolicyState.handleDeprecatedStorageSchemes(simplePassword);
- pwPolicyState.clearFailureLockout();
-
- if (isFirstWarning)
- {
- pwPolicyState.setWarnedTime();
-
- int numSeconds = pwPolicyState.getSecondsUntilExpiration();
- String timeToExpiration = secondsToTimeString(numSeconds);
-
- int msgID = MSGID_BIND_PASSWORD_EXPIRING;
- String message = getMessage(msgID, timeToExpiration);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.PASSWORD_EXPIRING, bindDN,
- msgID, message);
- }
-
- if (isGraceLogin)
- {
- pwPolicyState.updateGraceLoginTimes();
- }
-
- pwPolicyState.setLastLoginTime();
- }
- else
- {
- int msgID = MSGID_BIND_OPERATION_WRONG_PASSWORD;
- String message = getMessage(msgID);
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
-
- if (pwPolicyState.getPolicy().getLockoutFailureCount() > 0)
- {
- pwPolicyState.updateAuthFailureTimes();
- if (pwPolicyState.lockedDueToFailures())
- {
- AccountStatusNotificationType notificationType;
-
- int lockoutDuration = pwPolicyState.getSecondsUntilUnlock();
- if (lockoutDuration > -1)
- {
- notificationType = AccountStatusNotificationType.
- ACCOUNT_TEMPORARILY_LOCKED;
- msgID = MSGID_BIND_ACCOUNT_TEMPORARILY_LOCKED;
- message = getMessage(msgID,
- secondsToTimeString(lockoutDuration));
- }
- else
- {
- notificationType = AccountStatusNotificationType.
- ACCOUNT_PERMANENTLY_LOCKED;
- msgID = MSGID_BIND_ACCOUNT_PERMANENTLY_LOCKED;
- message = getMessage(msgID);
- }
-
- pwPolicyState.generateAccountStatusNotification(
- notificationType, userEntryDN, msgID, message);
- }
- }
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_BIND_OPERATION_PASSWORD_VALIDATION_EXCEPTION;
- String message = getMessage(msgID, getExceptionMessage(e));
-
- setResultCode(DirectoryServer.getServerErrorResultCode());
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
- finally
- {
- // No matter what, make sure to unlock the user's entry.
- LockManager.unlock(bindDN, userLock);
- }
-
- break;
-
-
- case SASL:
- // Get the appropriate authentication handler for this request based
- // on the SASL mechanism. If there is none, then fail.
- SASLMechanismHandler saslHandler =
- DirectoryServer.getSASLMechanismHandler(saslMechanism);
- if (saslHandler == null)
- {
- setResultCode(ResultCode.AUTH_METHOD_NOT_SUPPORTED);
-
- int msgID = MSGID_BIND_OPERATION_UNKNOWN_SASL_MECHANISM;
- String message = getMessage(msgID, saslMechanism);
-
- appendErrorMessage(message);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
-
-
- // Check to see if the client has sufficient permission to perform the
- // bind.
- // NYI
-
-
- // Invoke the pre-operation bind plugins.
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationBindPlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result
- // and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logBindResponse(this);
- pluginConfigManager.invokePostResponseBindPlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break bindProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break bindProcessing;
- }
-
-
- // Actually process the SASL bind.
- saslHandler.processSASLBind(this);
-
-
- // If the server is operating in lockdown mode, then we will need to
- // ensure that the authentication was successful and performed as a
- // root user to continue.
- if (DirectoryServer.lockdownMode())
- {
- ResultCode resultCode = getResultCode();
- if (resultCode != ResultCode.SASL_BIND_IN_PROGRESS)
- {
- if ((resultCode != ResultCode.SUCCESS) ||
- (saslAuthUserEntry == null) ||
- (! DirectoryServer.isRootDN(saslAuthUserEntry.getDN())))
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- int msgID = MSGID_BIND_REJECTED_LOCKDOWN_MODE;
- setAuthFailureReason(msgID, getMessage(msgID));
-
- break bindProcessing;
- }
- }
- }
-
-
- // Create the password policy state object.
- String userDNString;
- if (saslAuthUserEntry == null)
- {
- pwPolicyState = null;
- userDNString = null;
- }
- else
- {
- try
- {
- // FIXME -- Need to have a way to enable debugging.
- pwPolicyState = new PasswordPolicyState(saslAuthUserEntry, false,
- false);
- userEntryDN = saslAuthUserEntry.getDN();
- userDNString = String.valueOf(userEntryDN);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResponseData(de);
- break bindProcessing;
- }
- }
-
-
- // Perform password policy checks that will need to be completed
- // regardless of whether the authentication was successful.
- if (pwPolicyState != null)
- {
- if (pwPolicyState.isDisabled())
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_DISABLED;
- String message = getMessage(msgID, userDNString);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
- else if (pwPolicyState.isAccountExpired())
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_EXPIRED;
- String message = getMessage(msgID, userDNString);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_EXPIRED, bindDN, msgID,
- message);
-
- break bindProcessing;
- }
-
- if (pwPolicyState.getPolicy().requireSecureAuthentication() &&
- (! clientConnection.isSecure()) &&
- (! saslHandler.isSecure(saslMechanism)))
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- int msgID = MSGID_BIND_OPERATION_INSECURE_SASL_BIND;
- String message = getMessage(msgID, saslMechanism, userDNString);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
-
- if (pwPolicyState.lockedDueToFailures())
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
- }
-
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_FAILURE_LOCKED;
- String message = getMessage(msgID, userDNString);
- setAuthFailureReason(msgID, message);
- break bindProcessing;
- }
-
- if (pwPolicyState.lockedDueToIdleInterval())
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
- }
-
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_IDLE_LOCKED;
- String message = getMessage(msgID, userDNString);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_IDLE_LOCKED, bindDN,
- msgID, message);
-
- break bindProcessing;
- }
-
-
- if (saslHandler.isPasswordBased(saslMechanism))
- {
- if (pwPolicyState.lockedDueToMaximumResetAge())
- {
- setResultCode(ResultCode.INVALID_CREDENTIALS);
-
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.ACCOUNT_LOCKED;
- }
-
- int msgID = MSGID_BIND_OPERATION_ACCOUNT_RESET_LOCKED;
- String message = getMessage(msgID, userDNString);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_RESET_LOCKED, bindDN,
- msgID, message);
-
- break bindProcessing;
- }
-
- if (pwPolicyState.isPasswordExpired())
- {
- if (pwPolicyErrorType == null)
- {
- pwPolicyErrorType = PasswordPolicyErrorType.PASSWORD_EXPIRED;
- }
-
- int maxGraceLogins
- = pwPolicyState.getPolicy().getGraceLoginCount();
- if ((maxGraceLogins > 0) && pwPolicyState.mayUseGraceLogin())
- {
- List<Long> graceLoginTimes =
- pwPolicyState.getGraceLoginTimes();
- if ((graceLoginTimes == null) ||
- (graceLoginTimes.size() < maxGraceLogins))
- {
- isGraceLogin = true;
- mustChangePassword = true;
-
- if (pwPolicyWarningType == null)
- {
- pwPolicyWarningType =
- PasswordPolicyWarningType.GRACE_LOGINS_REMAINING;
- pwPolicyWarningValue =
- maxGraceLogins - (graceLoginTimes.size() + 1);
- }
- }
- else
- {
- int msgID = MSGID_BIND_OPERATION_PASSWORD_EXPIRED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.PASSWORD_EXPIRED, bindDN,
- msgID, message);
-
- break bindProcessing;
- }
- }
- else
- {
- int msgID = MSGID_BIND_OPERATION_PASSWORD_EXPIRED;
- String message = getMessage(msgID, String.valueOf(bindDN));
-
- setResultCode(ResultCode.INVALID_CREDENTIALS);
- setAuthFailureReason(msgID, message);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.PASSWORD_EXPIRED, bindDN,
- msgID, message);
-
- break bindProcessing;
- }
- }
- else if (pwPolicyState.shouldWarn())
- {
- int numSeconds = pwPolicyState.getSecondsUntilExpiration();
- String timeToExpiration = secondsToTimeString(numSeconds);
-
- int msgID = MSGID_BIND_PASSWORD_EXPIRING;
- String message = getMessage(msgID, timeToExpiration);
- appendErrorMessage(message);
-
- if (pwPolicyWarningType == null)
- {
- pwPolicyWarningType =
- PasswordPolicyWarningType.TIME_BEFORE_EXPIRATION;
- pwPolicyWarningValue = numSeconds;
- }
-
- isFirstWarning = pwPolicyState.isFirstWarning();
- }
- }
- }
-
-
- // Determine whether the authentication was successful and perform
- // any remaining password policy processing accordingly. Also check
- // for a custom size/time limit.
- ResultCode resultCode = getResultCode();
- if (resultCode == ResultCode.SUCCESS)
- {
- if (pwPolicyState != null)
- {
- if (saslHandler.isPasswordBased(saslMechanism) &&
- pwPolicyState.mustChangePassword())
- {
- mustChangePassword = true;
- }
-
- if (isFirstWarning)
- {
- pwPolicyState.setWarnedTime();
-
- int numSeconds = pwPolicyState.getSecondsUntilExpiration();
- String timeToExpiration = secondsToTimeString(numSeconds);
-
- int msgID = MSGID_BIND_PASSWORD_EXPIRING;
- String message = getMessage(msgID, timeToExpiration);
-
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.PASSWORD_EXPIRING, bindDN,
- msgID, message);
- }
-
- if (isGraceLogin)
- {
- pwPolicyState.updateGraceLoginTimes();
- }
-
- pwPolicyState.setLastLoginTime();
-
-
- // See if the user's entry contains a custom size limit.
- AttributeType attrType =
- DirectoryServer.getAttributeType(OP_ATTR_USER_SIZE_LIMIT,
- true);
- List<Attribute> attrList =
- saslAuthUserEntry.getAttribute(attrType);
- if ((attrList != null) && (attrList.size() == 1))
- {
- Attribute a = attrList.get(0);
- LinkedHashSet<AttributeValue> values = a.getValues();
- Iterator<AttributeValue> iterator = values.iterator();
- if (iterator.hasNext())
- {
- AttributeValue v = iterator.next();
- if (iterator.hasNext())
- {
- int msgID = MSGID_BIND_MULTIPLE_USER_SIZE_LIMITS;
- String message = getMessage(msgID, userDNString);
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- else
- {
- try
- {
- sizeLimit = Integer.parseInt(v.getStringValue());
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_BIND_CANNOT_PROCESS_USER_SIZE_LIMIT;
- String message =
- getMessage(msgID, v.getStringValue(), userDNString);
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- }
- }
- }
-
-
- // See if the user's entry contains a custom time limit.
- attrType =
- DirectoryServer.getAttributeType(OP_ATTR_USER_TIME_LIMIT,
- true);
- attrList = saslAuthUserEntry.getAttribute(attrType);
- if ((attrList != null) && (attrList.size() == 1))
- {
- Attribute a = attrList.get(0);
- LinkedHashSet<AttributeValue> values = a.getValues();
- Iterator<AttributeValue> iterator = values.iterator();
- if (iterator.hasNext())
- {
- AttributeValue v = iterator.next();
- if (iterator.hasNext())
- {
- int msgID = MSGID_BIND_MULTIPLE_USER_TIME_LIMITS;
- String message = getMessage(msgID, userDNString);
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- else
- {
- try
- {
- timeLimit = Integer.parseInt(v.getStringValue());
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_BIND_CANNOT_PROCESS_USER_TIME_LIMIT;
- String message =
- getMessage(msgID, v.getStringValue(), userDNString);
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- }
- }
- }
-
-
- // See if the user's entry contains a custom lookthrough limit.
- attrType =
- DirectoryServer.getAttributeType(
- OP_ATTR_USER_LOOKTHROUGH_LIMIT, true);
- attrList = saslAuthUserEntry.getAttribute(attrType);
- if ((attrList != null) && (attrList.size() == 1))
- {
- Attribute a = attrList.get(0);
- LinkedHashSet<AttributeValue> values = a.getValues();
- Iterator<AttributeValue> iterator = values.iterator();
- if (iterator.hasNext())
- {
- AttributeValue v = iterator.next();
- if (iterator.hasNext())
- {
- int msgID = MSGID_BIND_MULTIPLE_USER_LOOKTHROUGH_LIMITS;
- String message = getMessage(msgID, userDNString);
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- else
- {
- try
- {
- lookthroughLimit = Integer.parseInt(v.getStringValue());
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID =
- MSGID_BIND_CANNOT_PROCESS_USER_LOOKTHROUGH_LIMIT;
- String message =
- getMessage(msgID, v.getStringValue(), userDNString);
- logError(ErrorLogCategory.CORE_SERVER,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- }
- }
- }
- }
- }
- }
- else if (resultCode == ResultCode.SASL_BIND_IN_PROGRESS)
- {
- // FIXME -- Is any special processing needed here?
- }
- else
- {
- if (pwPolicyState != null)
- {
- if (saslHandler.isPasswordBased(saslMechanism))
- {
-
- if (pwPolicyState.getPolicy().getLockoutFailureCount() > 0)
- {
- pwPolicyState.updateAuthFailureTimes();
- if (pwPolicyState.lockedDueToFailures())
- {
- AccountStatusNotificationType notificationType;
- int msgID;
- String message;
-
- int lockoutDuration = pwPolicyState.getSecondsUntilUnlock();
- if (lockoutDuration > -1)
- {
- notificationType = AccountStatusNotificationType.
- ACCOUNT_TEMPORARILY_LOCKED;
- msgID = MSGID_BIND_ACCOUNT_TEMPORARILY_LOCKED;
- message = getMessage(msgID,
- secondsToTimeString(lockoutDuration));
- }
- else
- {
- notificationType = AccountStatusNotificationType.
- ACCOUNT_PERMANENTLY_LOCKED;
- msgID = MSGID_BIND_ACCOUNT_PERMANENTLY_LOCKED;
- message = getMessage(msgID);
- }
-
- pwPolicyState.generateAccountStatusNotification(
- notificationType, userEntryDN, msgID, message);
- }
- }
- }
- }
- }
-
- break;
-
-
- default:
- // Send a protocol error response to the client and disconnect.
- // NYI
- return;
- }
- }
-
-
- // Update the user's account with any password policy changes that may be
- // required.
- try
- {
- if (pwPolicyState != null)
- {
- pwPolicyState.updateUserEntry();
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResponseData(de);
- }
-
-
- // Invoke the post-operation bind plugins.
- if (! skipPostOperation)
- {
- PostOperationPluginResult postOpResult =
- pluginConfigManager.invokePostOperationBindPlugins(this);
- if (postOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result
- // and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logBindResponse(this);
- pluginConfigManager.invokePostResponseBindPlugins(this);
- return;
- }
- }
-
-
- // Update the authentication information for the user.
- if ((getResultCode() == ResultCode.SUCCESS) && (authInfo != null))
- {
- authenticatedUserEntry = authInfo.getAuthenticationEntry();
- clientConnection.setAuthenticationInfo(authInfo);
- clientConnection.setSizeLimit(sizeLimit);
- clientConnection.setTimeLimit(timeLimit);
- clientConnection.setLookthroughLimit(lookthroughLimit);
- clientConnection.setMustChangePassword(mustChangePassword);
-
- if (returnAuthzID)
- {
- responseControls.add(new AuthorizationIdentityResponseControl(
- authInfo.getAuthorizationDN()));
- }
- }
-
-
- // See if we need to send a password policy control to the client. If so,
- // then add it to the response.
- if (getResultCode() == ResultCode.SUCCESS)
- {
- if (pwPolicyControlRequested)
- {
- PasswordPolicyResponseControl pwpControl =
- new PasswordPolicyResponseControl(pwPolicyWarningType,
- pwPolicyWarningValue,
- pwPolicyErrorType);
- responseControls.add(pwpControl);
- }
- else
- {
- if (pwPolicyErrorType == PasswordPolicyErrorType.PASSWORD_EXPIRED)
- {
- responseControls.add(new PasswordExpiredControl());
- }
- else if (pwPolicyWarningType ==
- PasswordPolicyWarningType.TIME_BEFORE_EXPIRATION)
- {
- responseControls.add(new PasswordExpiringControl(
- pwPolicyWarningValue));
- }
- }
- }
- else
- {
- if (pwPolicyControlRequested)
- {
- PasswordPolicyResponseControl pwpControl =
- new PasswordPolicyResponseControl(pwPolicyWarningType,
- pwPolicyWarningValue,
- pwPolicyErrorType);
- responseControls.add(pwpControl);
- }
- else
- {
- if (pwPolicyErrorType == PasswordPolicyErrorType.PASSWORD_EXPIRED)
- {
- responseControls.add(new PasswordExpiredControl());
- }
- }
- }
-
-
- // Unset the "bind in progress" flag to allow other operations to be
- // processed.
- // FIXME -- Make sure this also gets unset at every possible point at which
- // the bind could fail and this method could return early.
- clientConnection.setBindInProgress(false);
-
-
- // Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
-
-
- // Send the bind response to the client.
- clientConnection.sendResponse(this);
-
-
- // Log the bind response.
- logBindResponse(this);
-
-
- // Invoke the post-response bind plugins.
- pluginConfigManager.invokePostResponseBindPlugins(this);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelResult cancel(CancelRequest cancelRequest)
- {
- cancelRequest.addResponseMessage(getMessage(MSGID_CANNOT_CANCEL_BIND));
- return CancelResult.CANNOT_CANCEL;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelRequest getCancelRequest()
- {
- return null;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
- {
- // Bind operations cannot be canceled.
- return false;
- }
-
+ public abstract void setUserEntryDN(DN userEntryDN);
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void toString(StringBuilder buffer)
- {
- buffer.append("BindOperation(connID=");
- buffer.append(clientConnection.getConnectionID());
- buffer.append(", opID=");
- buffer.append(operationID);
- buffer.append(", protocol=\"");
- buffer.append(clientConnection.getProtocol());
- buffer.append(" ");
- buffer.append(protocolVersion);
- buffer.append("\", dn=");
- buffer.append(rawBindDN);
- buffer.append(", authType=");
- buffer.append(authType);
- buffer.append(")");
- }
}
-
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/BindOperationBasis.java b/opendj-sdk/opends/src/server/org/opends/server/core/BindOperationBasis.java
new file mode 100644
index 0000000..541d04a
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/BindOperationBasis.java
@@ -0,0 +1,959 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_AUTH_TYPE;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_BIND_DN;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ERROR_MESSAGE;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_MATCHED_DN;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_PROCESSING_TIME;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_REFERRAL_URLS;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_RESULT_CODE;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_SASL_MECHANISM;
+import static org.opends.server.loggers.AccessLogger.logBindRequest;
+import static org.opends.server.loggers.AccessLogger.logBindResponse;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.messages.CoreMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.plugin.PreParsePluginResult;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.AuthenticationInfo;
+import org.opends.server.types.AuthenticationType;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.operation.PreParseBindOperation;
+import org.opends.server.workflowelement.localbackend.*;
+
+
+
+
+/**
+ * This class defines an operation that may be used to authenticate a user to
+ * the Directory Server. Note that for security restrictions, response messages
+ * that may be returned to the client must be carefully cleaned to ensure that
+ * they do not provide a malicious client with information that may be useful in
+ * an attack. This does impact the debugability of the server, but that can
+ * be addressed by calling the <CODE>setAuthFailureReason</CODE> method, which
+ * can provide a reason for a failure in a form that will not be returned to the
+ * client but may be written to a log file.
+ */
+public class BindOperationBasis
+ extends AbstractOperation
+ implements BindOperation, PreParseBindOperation
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
+
+ // The credentials used for SASL authentication.
+ private ASN1OctetString saslCredentials;
+
+ // The server SASL credentials provided to the client in the response.
+ private ASN1OctetString serverSASLCredentials;
+
+ // The authentication info for this bind operation.
+ private AuthenticationInfo authInfo = null;
+
+ // The authentication type used for this bind operation.
+ private AuthenticationType authType;
+
+ // The raw, unprocessed bind DN as contained in the client request.
+ private ByteString rawBindDN;
+
+ // The password used for simple authentication.
+ private ByteString simplePassword;
+
+ // The bind DN used for this bind operation.
+ private DN bindDN;
+
+ // The DN of the user entry that is attempting to authenticate.
+ private DN userEntryDN;
+
+ // The DN of the user as whom a SASL authentication was attempted (regardless
+ // of whether the authentication was successful) for the purpose of updating
+ // password policy state information.
+ private Entry saslAuthUserEntry;
+
+ // The unique ID associated with the failure reason message.
+ private int authFailureID;
+
+ // The set of response controls for this bind operation.
+ private List<Control> responseControls;
+
+ // A message explaining the reason for the authentication failure.
+ private String authFailureReason;
+
+ // The SASL mechanism used for SASL authentication.
+ private String saslMechanism;
+
+ // A string representation of the protocol version for this bind operation.
+ private String protocolVersion;
+
+ /**
+ * Creates a new simple bind operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param protocolVersion The string representation of the protocol version
+ * associated with this bind request.
+ * @param rawBindDN The raw, unprocessed bind DN as provided in the
+ * request from the client.
+ * @param simplePassword The password to use for the simple
+ * authentication.
+ */
+ public BindOperationBasis(ClientConnection clientConnection, long operationID,
+ int messageID, List<Control> requestControls,
+ String protocolVersion, ByteString rawBindDN,
+ ByteString simplePassword)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.protocolVersion = protocolVersion;
+ this.authType = AuthenticationType.SIMPLE;
+ this.saslMechanism = null;
+ this.saslCredentials = null;
+
+ if (rawBindDN == null)
+ {
+ this.rawBindDN = new ASN1OctetString();
+ }
+ else
+ {
+ this.rawBindDN = rawBindDN;
+ }
+
+ if (simplePassword == null)
+ {
+ this.simplePassword = new ASN1OctetString();
+ }
+ else
+ {
+ this.simplePassword = simplePassword;
+ }
+
+ bindDN = null;
+ userEntryDN = null;
+ responseControls = new ArrayList<Control>(0);
+ authFailureID = 0;
+ authFailureReason = null;
+ saslAuthUserEntry = null;
+ }
+
+
+
+ /**
+ * Creates a new SASL bind operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param protocolVersion The string representation of the protocol version
+ * associated with this bind request.
+ * @param rawBindDN The raw, unprocessed bind DN as provided in the
+ * request from the client.
+ * @param saslMechanism The SASL mechanism included in the request.
+ * @param saslCredentials The optional SASL credentials included in the
+ * request.
+ */
+ public BindOperationBasis(ClientConnection clientConnection, long operationID,
+ int messageID, List<Control> requestControls,
+ String protocolVersion, ByteString rawBindDN,
+ String saslMechanism, ASN1OctetString saslCredentials)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.protocolVersion = protocolVersion;
+ this.authType = AuthenticationType.SASL;
+ this.saslMechanism = saslMechanism;
+ this.saslCredentials = saslCredentials;
+ this.simplePassword = null;
+
+ if (rawBindDN == null)
+ {
+ this.rawBindDN = new ASN1OctetString();
+ }
+ else
+ {
+ this.rawBindDN = rawBindDN;
+ }
+
+ bindDN = null;
+ userEntryDN = null;
+ responseControls = new ArrayList<Control>(0);
+ authFailureID = 0;
+ authFailureReason = null;
+ saslAuthUserEntry = null;
+ }
+
+
+
+ /**
+ * Creates a new simple bind operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param protocolVersion The string representation of the protocol version
+ * associated with this bind request.
+ * @param bindDN The bind DN for this bind operation.
+ * @param simplePassword The password to use for the simple
+ * authentication.
+ */
+ public BindOperationBasis(ClientConnection clientConnection, long operationID,
+ int messageID, List<Control> requestControls,
+ String protocolVersion, DN bindDN,
+ ByteString simplePassword)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.protocolVersion = protocolVersion;
+ this.authType = AuthenticationType.SIMPLE;
+ this.bindDN = bindDN;
+ this.saslMechanism = null;
+ this.saslCredentials = null;
+
+ if (bindDN == null)
+ {
+ rawBindDN = new ASN1OctetString();
+ }
+ else
+ {
+ rawBindDN = new ASN1OctetString(bindDN.toString());
+ }
+
+ if (simplePassword == null)
+ {
+ this.simplePassword = new ASN1OctetString();
+ }
+ else
+ {
+ this.simplePassword = simplePassword;
+ }
+
+ responseControls = new ArrayList<Control>(0);
+ authFailureID = 0;
+ authFailureReason = null;
+ saslAuthUserEntry = null;
+ userEntryDN = null;
+ }
+
+
+
+ /**
+ * Creates a new SASL bind operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param protocolVersion The string representation of the protocol version
+ * associated with this bind request.
+ * @param bindDN The bind DN for this bind operation.
+ * @param saslMechanism The SASL mechanism included in the request.
+ * @param saslCredentials The optional SASL credentials included in the
+ * request.
+ */
+ public BindOperationBasis(ClientConnection clientConnection, long operationID,
+ int messageID, List<Control> requestControls,
+ String protocolVersion, DN bindDN,
+ String saslMechanism, ASN1OctetString saslCredentials)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.protocolVersion = protocolVersion;
+ this.authType = AuthenticationType.SASL;
+ this.bindDN = bindDN;
+ this.saslMechanism = saslMechanism;
+ this.saslCredentials = saslCredentials;
+ this.simplePassword = null;
+
+ if (bindDN == null)
+ {
+ rawBindDN = new ASN1OctetString();
+ }
+ else
+ {
+ rawBindDN = new ASN1OctetString(bindDN.toString());
+ }
+
+ responseControls = new ArrayList<Control>(0);
+ authFailureID = 0;
+ authFailureReason = null;
+ saslAuthUserEntry = null;
+ userEntryDN = null;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final AuthenticationType getAuthenticationType()
+ {
+ return authType;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ByteString getRawBindDN()
+ {
+ return rawBindDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawBindDN(ByteString rawBindDN)
+ {
+ if (rawBindDN == null)
+ {
+ this.rawBindDN = new ASN1OctetString();
+ }
+ else
+ {
+ this.rawBindDN = rawBindDN;
+ }
+
+ bindDN = null;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getBindDN()
+ {
+ try
+ {
+ if (bindDN == null)
+ {
+ bindDN = DN.decode(rawBindDN);
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResultCode(ResultCode.INVALID_CREDENTIALS);
+ setAuthFailureReason(de.getMessageID(), de.getErrorMessage());
+ }
+ return bindDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ByteString getSimplePassword()
+ {
+ return simplePassword;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setSimplePassword(ByteString simplePassword)
+ {
+ if (simplePassword == null)
+ {
+ this.simplePassword = new ASN1OctetString();
+ }
+ else
+ {
+ this.simplePassword = simplePassword;
+ }
+
+ authType = AuthenticationType.SIMPLE;
+ saslMechanism = null;
+ saslCredentials = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String getSASLMechanism()
+ {
+ return saslMechanism;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ASN1OctetString getSASLCredentials()
+ {
+ return saslCredentials;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setSASLCredentials(String saslMechanism,
+ ASN1OctetString saslCredentials)
+ {
+ this.saslMechanism = saslMechanism;
+ this.saslCredentials = saslCredentials;
+
+ authType = AuthenticationType.SASL;
+ simplePassword = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ASN1OctetString getServerSASLCredentials()
+ {
+ return serverSASLCredentials;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setServerSASLCredentials(ASN1OctetString
+ serverSASLCredentials)
+ {
+ this.serverSASLCredentials = serverSASLCredentials;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Entry getSASLAuthUserEntry()
+ {
+ return saslAuthUserEntry;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setSASLAuthUserEntry(Entry saslAuthUserEntry)
+ {
+ this.saslAuthUserEntry = saslAuthUserEntry;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String getAuthFailureReason()
+ {
+ return authFailureReason;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int getAuthFailureID()
+ {
+ return authFailureID;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setAuthFailureReason(int id, String reason)
+ {
+ if (id < 0)
+ {
+ authFailureID = 0;
+ }
+ else
+ {
+ authFailureID = id;
+ }
+
+ authFailureReason = reason;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getUserEntryDN()
+ {
+ return userEntryDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final AuthenticationInfo getAuthenticationInfo()
+ {
+ return authInfo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setAuthenticationInfo(AuthenticationInfo authInfo)
+ {
+ this.authInfo = authInfo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final OperationType getOperationType()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ return OperationType.BIND;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message,
+ int messageID)
+ {
+ // Since bind operations can't be cancelled, we don't need to do anything
+ // but forward the request on to the client connection.
+ clientConnection.disconnect(disconnectReason, sendNotification, message,
+ messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final String[][] getRequestLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ if (authType == AuthenticationType.SASL)
+ {
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_BIND_DN, String.valueOf(rawBindDN) },
+ new String[] { LOG_ELEMENT_AUTH_TYPE, authType.toString() },
+ new String[] { LOG_ELEMENT_SASL_MECHANISM, saslMechanism }
+ };
+ }
+ else
+ {
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_BIND_DN, String.valueOf(rawBindDN) },
+ new String[] { LOG_ELEMENT_AUTH_TYPE, authType.toString() }
+ };
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final String[][] getResponseLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ String resultCode = String.valueOf(getResultCode().getIntValue());
+
+ String errorMessage;
+ StringBuilder errorMessageBuffer = getErrorMessage();
+ if (errorMessageBuffer == null)
+ {
+ errorMessage = null;
+ }
+ else
+ {
+ errorMessage = errorMessageBuffer.toString();
+ }
+
+ String matchedDNStr;
+ DN matchedDN = getMatchedDN();
+ if (matchedDN == null)
+ {
+ matchedDNStr = null;
+ }
+ else
+ {
+ matchedDNStr = matchedDN.toString();
+ }
+
+ String referrals;
+ List<String> referralURLs = getReferralURLs();
+ if ((referralURLs == null) || referralURLs.isEmpty())
+ {
+ referrals = null;
+ }
+ else
+ {
+ StringBuilder buffer = new StringBuilder();
+ Iterator<String> iterator = referralURLs.iterator();
+ buffer.append(iterator.next());
+
+ while (iterator.hasNext())
+ {
+ buffer.append(", ");
+ buffer.append(iterator.next());
+ }
+
+ referrals = buffer.toString();
+ }
+
+ String processingTime =
+ String.valueOf(getProcessingTime());
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
+ new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
+ new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
+ new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
+ new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final List<Control> getResponseControls()
+ {
+ return responseControls;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void addResponseControl(Control control)
+ {
+ responseControls.add(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void removeResponseControl(Control control)
+ {
+ responseControls.remove(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final CancelResult cancel(CancelRequest cancelRequest)
+ {
+ cancelRequest.addResponseMessage(getMessage(MSGID_CANNOT_CANCEL_BIND));
+ return CancelResult.CANNOT_CANCEL;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final CancelRequest getCancelRequest()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public
+ boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ // Bind operations cannot be canceled.
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void toString(StringBuilder buffer)
+ {
+ buffer.append("BindOperation(connID=");
+ buffer.append(clientConnection.getConnectionID());
+ buffer.append(", opID=");
+ buffer.append(operationID);
+ buffer.append(", protocol=\"");
+ buffer.append(clientConnection.getProtocol());
+ buffer.append(" ");
+ buffer.append(protocolVersion);
+ buffer.append(", dn=");
+ buffer.append(rawBindDN);
+ buffer.append(", authType=");
+ buffer.append(authType);
+ buffer.append(")");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setUserEntryDN(DN userEntryDN)
+ {
+ this.userEntryDN = userEntryDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getProtocolVersion()
+ {
+ return protocolVersion;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProtocolVersion(String protocolVersion)
+ {
+ this.protocolVersion = protocolVersion;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void run()
+ {
+ // Start the processing timer and initially set the result to indicate that
+ // the result is unknown.
+ setProcessingStartTime();
+ ClientConnection clientConnection = getClientConnection();
+
+ setResultCode(ResultCode.UNDEFINED);
+
+ // Set a flag to indicate that a bind operation is in progress. This should
+ // ensure that no new operations will be accepted for this client until the
+ // bind is complete.
+ clientConnection.setBindInProgress(true);
+
+ // Wipe out any existing authentication for the client connection and create
+ // a placeholder that will be used if the bind is successful.
+ clientConnection.setUnauthenticated();
+
+ // Abandon any operations that may be in progress for the client.
+ String cancelReason = getMessage(MSGID_CANCELED_BY_BIND_REQUEST);
+ CancelRequest cancelRequest = new CancelRequest(true, cancelReason);
+ clientConnection.cancelAllOperationsExcept(cancelRequest, getMessageID());
+
+
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+
+ // Create a labeled block of code that we can break out of if a problem is
+ // detected.
+ bindProcessing:
+ {
+ // Invoke the pre-parse bind plugins.
+ PreParsePluginResult preParseResult =
+ pluginConfigManager.invokePreParseBindPlugins(this);
+ if (preParseResult.connectionTerminated())
+ {
+ // There's no point in continuing with anything. Log the request and
+ // result and return.
+ setResultCode(ResultCode.CANCELED);
+
+ int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
+ appendErrorMessage(getMessage(msgID));
+
+ setProcessingStopTime();
+
+ logBindRequest(this);
+ logBindResponse(this);
+ return;
+ }
+ else if (preParseResult.sendResponseImmediately())
+ {
+ logBindRequest(this);
+ break bindProcessing;
+ }
+ else if (preParseResult.skipCoreProcessing())
+ {
+ break bindProcessing;
+ }
+
+ // Log the bind request message.
+ logBindRequest(this);
+
+ // Process the bind DN to convert it from the raw form as provided by the
+ // client into the form required for the rest of the bind processing.
+ DN bindDN = getBindDN();
+ if (bindDN == null){
+ break bindProcessing;
+ }
+
+ // If this is a simple bind
+ // Then check wether the bind DN is actually one of the alternate root DNs
+ // defined in the server. If so, then replace it with the actual DN
+ // for that user.
+ switch (getAuthenticationType())
+ {
+ case SIMPLE:
+ DN actualRootDN = DirectoryServer.getActualRootBindDN(bindDN);
+ if (actualRootDN != null)
+ {
+ bindDN = actualRootDN;
+ }
+ }
+
+
+ // Retrieve the network group attached to the client connection
+ // and get a workflow to process the operation.
+ NetworkGroup ng = getClientConnection().getNetworkGroup();
+ Workflow workflow = ng.getWorkflowCandidate(bindDN);
+ if (workflow == null)
+ {
+ // We have found no workflow for the requested base DN, just return
+ // a no such entry result code and stop the processing.
+ updateOperationErrMsgAndResCode();
+ break bindProcessing;
+ }
+ workflow.execute(this);
+ }
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelResult() == CancelResult.CANCELED)
+ {
+ setProcessingStopTime();
+ logBindResponse(this);
+ invokePostResponsePlugins();
+ return;
+ }
+
+ // Unset the "bind in progress" flag to allow other operations to be
+ // processed.
+ // FIXME -- Make sure this also gets unset at every possible point at which
+ // the bind could fail and this method could return early.
+ clientConnection.setBindInProgress(false);
+
+ // Stop the processing timer.
+ setProcessingStopTime();
+
+ // Send the bind response to the client.
+ clientConnection.sendResponse(this);
+
+ // Log the bind response.
+ logBindResponse(this);
+
+ // Check wether there are local operations in attachments
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+ if (localOperations != null && (! localOperations.isEmpty())){
+ for (Object localOp : localOperations)
+ {
+ LocalBackendBindOperation localOperation =
+ (LocalBackendBindOperation)localOp;
+ // Invoke the post-response bind plugins.
+ pluginConfigManager.invokePostResponseBindPlugins(localOperation);
+ }
+ }
+ }
+
+ /**
+ * Updates the error message and the result code of the operation.
+ *
+ * This method is called because no workflows were found to process
+ * the operation.
+ */
+ private void updateOperationErrMsgAndResCode()
+ {
+ int msgID = MSGID_BIND_OPERATION_UNKNOWN_USER;
+ String message = getMessage(msgID, String.valueOf(getBindDN()));
+
+ setResultCode(ResultCode.INVALID_CREDENTIALS);
+ setAuthFailureReason(msgID, message);
+ }
+
+ /**
+ * Execute the postResponseBindPlugins.
+ */
+ private void invokePostResponsePlugins()
+ {
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+ // Check wether there are local operations in attachments
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+
+ if (localOperations != null && (! localOperations.isEmpty())){
+ for (Object localOp : localOperations)
+ {
+ LocalBackendBindOperation localOperation =
+ (LocalBackendBindOperation)localOp;
+ // Invoke the post-response bind plugins.
+ pluginConfigManager.invokePostResponseBindPlugins(localOperation);
+ }
+ }
+ }
+
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/BindOperationWrapper.java b/opendj-sdk/opends/src/server/org/opends/server/core/BindOperationWrapper.java
new file mode 100644
index 0000000..ddb784c
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/BindOperationWrapper.java
@@ -0,0 +1,691 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AuthenticationInfo;
+import org.opends.server.types.AuthenticationType;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.ResultCode;
+
+/**
+ * This abstract class wraps/decorates a given bind operation.
+ * This class will be extended by sub-classes to enhance the
+ * functionnality of the BindOperationBasis.
+ */
+public abstract class BindOperationWrapper implements BindOperation
+{
+ private BindOperation bind;
+
+ /**
+ * Creates a new bind operation based on the provided bind operation.
+ *
+ * @param bind The bind operation to wrap
+ */
+ protected BindOperationWrapper(BindOperation bind){
+ this.bind = bind;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addRequestControl(Control control)
+ {
+ bind.addRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addResponseControl(Control control)
+ {
+ bind.addResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendAdditionalLogMessage(String message)
+ {
+ bind.appendAdditionalLogMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendErrorMessage(String message)
+ {
+ bind.appendErrorMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult cancel(CancelRequest cancelRequest)
+ {
+ return bind.cancel(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message, int messageID)
+ {
+ bind.disconnectClient(disconnectReason, sendNotification, message,
+ messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean dontSynchronize()
+ {
+ return bind.dontSynchronize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getAdditionalLogMessage()
+ {
+ return bind.getAdditionalLogMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getAttachment(String name)
+ {
+ return bind.getAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<String, Object> getAttachments()
+ {
+ return bind.getAttachments();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AuthenticationInfo getAuthenticationInfo()
+ {
+ return bind.getAuthenticationInfo();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AuthenticationType getAuthenticationType()
+ {
+ return bind.getAuthenticationType();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getAuthFailureID()
+ {
+ return bind.getAuthFailureID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getAuthFailureReason()
+ {
+ return bind.getAuthFailureReason();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getAuthorizationDN()
+ {
+ return bind.getAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry getAuthorizationEntry()
+ {
+ return bind.getAuthorizationEntry();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getBindDN()
+ {
+ return bind.getBindDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelRequest getCancelRequest()
+ {
+ return bind.getCancelRequest();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult getCancelResult()
+ {
+ return bind.getCancelResult();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClientConnection getClientConnection()
+ {
+ return bind.getClientConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getCommonLogElements()
+ {
+ return bind.getCommonLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getConnectionID()
+ {
+ return bind.getConnectionID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getErrorMessage()
+ {
+ return bind.getErrorMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getMatchedDN()
+ {
+ return bind.getMatchedDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMessageID()
+ {
+ return bind.getMessageID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getOperationID()
+ {
+ return bind.getOperationID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public OperationType getOperationType()
+ {
+ return bind.getOperationType();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStartTime()
+ {
+ return bind.getProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStopTime()
+ {
+ return bind.getProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingTime()
+ {
+ return bind.getProcessingTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString getRawBindDN()
+ {
+ return bind.getRawBindDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<String> getReferralURLs()
+ {
+ return bind.getReferralURLs();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getRequestControls()
+ {
+ return bind.getRequestControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getRequestLogElements()
+ {
+ return bind.getRequestLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getResponseControls()
+ {
+ return bind.getResponseControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getResponseLogElements()
+ {
+ return bind.getResponseLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultCode getResultCode()
+ {
+ return bind.getResultCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry getSASLAuthUserEntry()
+ {
+ return bind.getSASLAuthUserEntry();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ASN1OctetString getSASLCredentials()
+ {
+ return bind.getSASLCredentials();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSASLMechanism()
+ {
+ return bind.getSASLMechanism();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ASN1OctetString getServerSASLCredentials()
+ {
+ return bind.getServerSASLCredentials();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString getSimplePassword()
+ {
+ return bind.getSimplePassword();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getUserEntryDN()
+ {
+ return bind.getUserEntryDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void indicateCancelled(CancelRequest cancelRequest)
+ {
+ bind.indicateCancelled(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isInternalOperation()
+ {
+ return bind.isInternalOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSynchronizationOperation()
+ {
+ return bind.isSynchronizationOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void operationCompleted()
+ {
+ bind.operationCompleted();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object removeAttachment(String name)
+ {
+ return bind.removeAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeRequestControl(Control control)
+ {
+ bind.removeRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeResponseControl(Control control)
+ {
+ bind.removeResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAdditionalLogMessage(StringBuilder additionalLogMessage)
+ {
+ bind.setAdditionalLogMessage(additionalLogMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object setAttachment(String name, Object value)
+ {
+ return bind.setAttachment(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttachments(Map<String, Object> attachments)
+ {
+ bind.setAttachments(attachments);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAuthenticationInfo(AuthenticationInfo authInfo)
+ {
+ bind.setAuthenticationInfo(authInfo);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAuthFailureReason(int id, String reason)
+ {
+ bind.setAuthFailureReason(id, reason);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAuthorizationEntry(Entry authorizationEntry)
+ {
+ bind.setAuthorizationEntry(authorizationEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ return bind.setCancelRequest(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCancelResult(CancelResult cancelResult)
+ {
+ bind.setCancelResult(cancelResult);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDontSynchronize(boolean dontSynchronize)
+ {
+ bind.setDontSynchronize(dontSynchronize);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setErrorMessage(StringBuilder errorMessage)
+ {
+ bind.setErrorMessage(errorMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInternalOperation(boolean isInternalOperation)
+ {
+ bind.setInternalOperation(isInternalOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMatchedDN(DN matchedDN)
+ {
+ bind.setMatchedDN(matchedDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStartTime()
+ {
+ bind.setProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStopTime()
+ {
+ bind.setProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawBindDN(ByteString rawBindDN)
+ {
+ bind.setRawBindDN(rawBindDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setReferralURLs(List<String> referralURLs)
+ {
+ bind.setReferralURLs(referralURLs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResponseData(DirectoryException directoryException)
+ {
+ bind.setResponseData(directoryException);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResultCode(ResultCode resultCode)
+ {
+ bind.setResultCode(resultCode);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSASLAuthUserEntry(Entry saslAuthUserEntry)
+ {
+ bind.setSASLAuthUserEntry(saslAuthUserEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSASLCredentials(String saslMechanism,
+ ASN1OctetString saslCredentials)
+ {
+ bind.setSASLCredentials(saslMechanism, saslCredentials);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setServerSASLCredentials(ASN1OctetString serverSASLCredentials)
+ {
+ bind.setServerSASLCredentials(serverSASLCredentials);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSimplePassword(ByteString simplePassword)
+ {
+ bind.setSimplePassword(simplePassword);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSynchronizationOperation(boolean isSynchronizationOperation)
+ {
+ bind.setSynchronizationOperation(isSynchronizationOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setUserEntryDN(DN userEntryDN){
+ bind.setUserEntryDN(userEntryDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return bind.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void toString(StringBuilder buffer)
+ {
+ bind.toString(buffer);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProtocolVersion(String protocolVersion)
+ {
+ bind.setProtocolVersion(protocolVersion);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getProtocolVersion()
+ {
+ return bind.getProtocolVersion();
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java
index 30bf972..1a3af75 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/CompareOperation.java
@@ -43,6 +43,7 @@
import org.opends.server.controls.ProxiedAuthV1Control;
import org.opends.server.controls.ProxiedAuthV2Control;
import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
@@ -56,7 +57,6 @@
import org.opends.server.types.Entry;
import org.opends.server.types.LDAPException;
import org.opends.server.types.LockManager;
-import org.opends.server.types.Operation;
import org.opends.server.types.OperationType;
import org.opends.server.types.Privilege;
import org.opends.server.types.ResultCode;
@@ -69,6 +69,8 @@
import static org.opends.server.core.CoreConstants.*;
import static org.opends.server.loggers.AccessLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
+
+import org.opends.server.loggers.debug.DebugLogger;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.DebugLogLevel;
import static org.opends.server.messages.CoreMessages.*;
@@ -84,14 +86,14 @@
* pair.
*/
public class CompareOperation
- extends Operation
+ extends AbstractOperation
implements PreParseCompareOperation, PreOperationCompareOperation,
PostOperationCompareOperation, PostResponseCompareOperation
{
/**
* The tracer object for the debug logger.
*/
- private static final DebugTracer TRACER = getTracer();
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
// The attribute type for this compare operation.
private AttributeType attributeType;
@@ -117,12 +119,6 @@
// The set of response controls for this compare operation.
private List<Control> responseControls;
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
// The attribute type for the compare operation.
private String rawAttributeType;
@@ -324,41 +320,6 @@
return entry;
}
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
-
/**
* {@inheritDoc}
*/
@@ -465,7 +426,7 @@
}
String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
+ String.valueOf(getProcessingTime());
return new String[][]
{
@@ -528,9 +489,12 @@
/**
- * {@inheritDoc}
+ * Performs the work of actually processing this operation. This
+ * should include all processing for the operation, including
+ * invoking plugins, logging messages, performing access control,
+ * managing synchronization, and any other work that might need to
+ * be done in the course of processing.
*/
- @Override()
public final void run()
{
setResultCode(ResultCode.UNDEFINED);
@@ -543,14 +507,14 @@
// Start the processing timer.
- processingStartTime = System.currentTimeMillis();
+ setProcessingStartTime();
// Check for and handle a request to cancel this operation.
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
return;
}
@@ -571,7 +535,7 @@
int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logCompareRequest(this);
logCompareResponse(this);
@@ -599,7 +563,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logCompareResponse(this);
pluginConfigManager.invokePostResponseComparePlugins(this);
return;
@@ -648,7 +612,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logCompareResponse(this);
pluginConfigManager.invokePostResponseComparePlugins(this);
return;
@@ -998,7 +962,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logCompareResponse(this);
pluginConfigManager.invokePostResponseComparePlugins(this);
return;
@@ -1017,7 +981,7 @@
int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logCompareResponse(this);
pluginConfigManager.invokePostResponseComparePlugins(this);
return;
@@ -1127,7 +1091,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logCompareResponse(this);
pluginConfigManager.invokePostResponseComparePlugins(this);
return;
@@ -1146,7 +1110,7 @@
int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logCompareResponse(this);
pluginConfigManager.invokePostResponseComparePlugins(this);
return;
@@ -1159,7 +1123,7 @@
// Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
// Send the compare response to the client.
@@ -1233,7 +1197,7 @@
* {@inheritDoc}
*/
@Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
+ public boolean setCancelRequest(CancelRequest cancelRequest)
{
this.cancelRequest = cancelRequest;
return true;
@@ -1257,5 +1221,6 @@
buffer.append(rawAttributeType);
buffer.append(")");
}
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DefaultAccessControlProvider.java b/opendj-sdk/opends/src/server/org/opends/server/core/DefaultAccessControlProvider.java
index 6800688..0c9867e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DefaultAccessControlProvider.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DefaultAccessControlProvider.java
@@ -30,11 +30,8 @@
import org.opends.server.api.AccessControlHandler;
import org.opends.server.api.AccessControlProvider;
import org.opends.server.config.ConfigException;
-import org.opends.server.types.InitializationException;
-import org.opends.server.types.Operation;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SearchResultReference;
import org.opends.server.types.*;
+import org.opends.server.workflowelement.localbackend.*;
/**
* This class implements a default access control provider for the
@@ -103,7 +100,7 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(AddOperation addOperation) {
+ public boolean isAllowed(LocalBackendAddOperation addOperation) {
return true;
}
@@ -112,7 +109,7 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(BindOperation bindOperation) {
+ public boolean isAllowed(LocalBackendBindOperation bindOperation) {
return true;
}
@@ -130,7 +127,7 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(DeleteOperation deleteOperation) {
+ public boolean isAllowed(LocalBackendDeleteOperation deleteOperation) {
return true;
}
@@ -148,7 +145,7 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(ModifyOperation modifyOperation) {
+ public boolean isAllowed(LocalBackendModifyOperation modifyOperation) {
return true;
}
@@ -166,7 +163,7 @@
* {@inheritDoc}
*/
@Override
- public boolean isAllowed(SearchOperation searchOperation) {
+ public boolean isAllowed(LocalBackendSearchOperation searchOperation) {
return true;
}
@@ -186,7 +183,8 @@
*/
@Override
public SearchResultEntry filterEntry(
- SearchOperation searchOperation, SearchResultEntry searchEntry) {
+ SearchOperation searchOperation,
+ SearchResultEntry searchEntry) {
// No implementation required.
return searchEntry;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java
index c28f696..56aa4d4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperation.java
@@ -26,169 +26,16 @@
*/
package org.opends.server.core;
-
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.locks.Lock;
-
-import org.opends.server.api.Backend;
-import org.opends.server.api.ChangeNotificationListener;
-import org.opends.server.api.ClientConnection;
-import org.opends.server.api.SynchronizationProvider;
-import org.opends.server.api.plugin.PostOperationPluginResult;
-import org.opends.server.api.plugin.PreOperationPluginResult;
-import org.opends.server.api.plugin.PreParsePluginResult;
-import org.opends.server.controls.LDAPAssertionRequestControl;
-import org.opends.server.controls.LDAPPreReadRequestControl;
-import org.opends.server.controls.LDAPPreReadResponseControl;
-import org.opends.server.controls.ProxiedAuthV1Control;
-import org.opends.server.controls.ProxiedAuthV2Control;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.types.AttributeType;
import org.opends.server.types.ByteString;
-import org.opends.server.types.CancelledOperationException;
-import org.opends.server.types.CancelRequest;
-import org.opends.server.types.CancelResult;
-import org.opends.server.types.Control;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.LDAPException;
-import org.opends.server.types.LockManager;
import org.opends.server.types.Operation;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.Privilege;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SynchronizationProviderResult;
-import org.opends.server.types.operation.PostOperationDeleteOperation;
-import org.opends.server.types.operation.PostResponseDeleteOperation;
-import org.opends.server.types.operation.PreOperationDeleteOperation;
-import org.opends.server.types.operation.PreParseDeleteOperation;
-
-import static org.opends.server.core.CoreConstants.*;
-import static org.opends.server.loggers.AccessLogger.*;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-import static org.opends.server.messages.CoreMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
-
/**
- * This class defines an operation that may be used to remove an entry from the
- * Directory Server.
+ * This interface defines an operation that may be used to remove an entry from
+ * the Directory Server.
*/
-public class DeleteOperation
- extends Operation
- implements PreParseDeleteOperation, PreOperationDeleteOperation,
- PostOperationDeleteOperation, PostResponseDeleteOperation
+public interface DeleteOperation extends Operation
{
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
-
-
-
- // The raw, unprocessed entry DN as included in the client request.
- private ByteString rawEntryDN;
-
- // The cancel request that has been issued for this delete operation.
- private CancelRequest cancelRequest;
-
- // The DN of the entry for the delete operation.
- private DN entryDN;
-
- // The proxied authorization target DN for this operation.
- private DN proxiedAuthorizationDN;
-
- // The entry to be deleted.
- private Entry entry;
-
- // The set of response controls for this delete operation.
- private List<Control> responseControls;
-
- // The change number that has been assigned to this operation.
- private long changeNumber;
-
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
-
-
- /**
- * Creates a new delete operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param rawEntryDN The raw, unprocessed DN of the entry to delete,
- * as included in the client request.
- */
- public DeleteOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- ByteString rawEntryDN)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.rawEntryDN = rawEntryDN;
-
- entry = null;
- entryDN = null;
- responseControls = new ArrayList<Control>();
- cancelRequest = null;
- changeNumber = -1;
- }
-
-
-
- /**
- * Creates a new delete operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param entryDN The entry DN for this delete operation.
- */
- public DeleteOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- DN entryDN)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.entryDN = entryDN;
-
- rawEntryDN = new ASN1OctetString(entryDN.toString());
- responseControls = new ArrayList<Control>();
- cancelRequest = null;
- changeNumber = -1;
- entry = null;
- }
-
-
/**
* Retrieves the raw, unprocessed entry DN as included in the client request.
@@ -197,12 +44,7 @@
*
* @return The raw, unprocessed entry DN as included in the client request.
*/
- public final ByteString getRawEntryDN()
- {
- return rawEntryDN;
- }
-
-
+ public abstract ByteString getRawEntryDN();
/**
* Specifies the raw, unprocessed entry DN as included in the client request.
@@ -212,14 +54,7 @@
* @param rawEntryDN The raw, unprocessed entry DN as included in the client
* request.
*/
- public final void setRawEntryDN(ByteString rawEntryDN)
- {
- this.rawEntryDN = rawEntryDN;
-
- entryDN = null;
- }
-
-
+ public abstract void setRawEntryDN(ByteString rawEntryDN);
/**
* Retrieves the DN of the entry to delete. This should not be called by
@@ -229,59 +64,7 @@
* @return The DN of the entry to delete, or <CODE>null</CODE> if the raw
* entry DN has not yet been processed.
*/
- public final DN getEntryDN()
- {
- return entryDN;
- }
-
-
-
- /**
- * Retrieves the entry to be deleted. This will not be available to pre-parse
- * plugins.
- *
- * @return The entry to be deleted, or <CODE>null</CODE> if the entry is not
- * yet available.
- */
- public final Entry getEntryToDelete()
- {
- return entry;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
+ public abstract DN getEntryDN();
/**
* Retrieves the change number that has been assigned to this operation.
@@ -290,12 +73,7 @@
* if none has been assigned yet or if there is no applicable
* synchronization mechanism in place that uses change numbers.
*/
- public final long getChangeNumber()
- {
- return changeNumber;
- }
-
-
+ public abstract long getChangeNumber();
/**
* Specifies the change number that has been assigned to this operation by the
@@ -304,131 +82,7 @@
* @param changeNumber The change number that has been assigned to this
* operation by the synchronization mechanism.
*/
- public final void setChangeNumber(long changeNumber)
- {
- this.changeNumber = changeNumber;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final OperationType getOperationType()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- return OperationType.DELETE;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void disconnectClient(DisconnectReason disconnectReason,
- boolean sendNotification, String message,
- int messageID)
- {
- // Before calling clientConnection.disconnect, we need to mark this
- // operation as cancelled so that the attempt to cancel it later won't cause
- // an unnecessary delay.
- setCancelResult(CancelResult.CANCELED);
-
- clientConnection.disconnect(disconnectReason, sendNotification, message,
- messageID);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final String[][] getRequestLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- return new String[][]
- {
- new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }
- };
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final String[][] getResponseLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- String resultCode = String.valueOf(getResultCode().getIntValue());
-
- String errorMessage;
- StringBuilder errorMessageBuffer = getErrorMessage();
- if (errorMessageBuffer == null)
- {
- errorMessage = null;
- }
- else
- {
- errorMessage = errorMessageBuffer.toString();
- }
-
- String matchedDNStr;
- DN matchedDN = getMatchedDN();
- if (matchedDN == null)
- {
- matchedDNStr = null;
- }
- else
- {
- matchedDNStr = matchedDN.toString();
- }
-
- String referrals;
- List<String> referralURLs = getReferralURLs();
- if ((referralURLs == null) || referralURLs.isEmpty())
- {
- referrals = null;
- }
- else
- {
- StringBuilder buffer = new StringBuilder();
- Iterator<String> iterator = referralURLs.iterator();
- buffer.append(iterator.next());
-
- while (iterator.hasNext())
- {
- buffer.append(", ");
- buffer.append(iterator.next());
- }
-
- referrals = buffer.toString();
- }
-
- String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
-
- return new String[][]
- {
- new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
- new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
- new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
- new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
- new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
- };
- }
-
-
+ public abstract void setChangeNumber(long changeNumber);
/**
* Retrieves the proxied authorization DN for this operation if proxied
@@ -438,1021 +92,18 @@
* authorization has been requested, or {@code null} if proxied
* authorization has not been requested.
*/
- public DN getProxiedAuthorizationDN()
- {
- return proxiedAuthorizationDN;
- }
-
-
+ public abstract DN getProxiedAuthorizationDN();
/**
- * {@inheritDoc}
+ * Set the proxied authorization DN for this operation if proxied
+ * authorization has been requested.
+ *
+ * @param proxiedAuthorizationDN
+ * The proxied authorization DN for this operation if proxied
+ * authorization has been requested, or {@code null} if proxied
+ * authorization has not been requested.
*/
- @Override()
- public final List<Control> getResponseControls()
- {
- return responseControls;
- }
+ public abstract void setProxiedAuthorizationDN(DN proxiedAuthorizationDN);
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void addResponseControl(Control control)
- {
- responseControls.add(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void removeResponseControl(Control control)
- {
- responseControls.remove(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void run()
- {
- setResultCode(ResultCode.UNDEFINED);
-
-
- // Get the plugin config manager that will be used for invoking plugins.
- PluginConfigManager pluginConfigManager =
- DirectoryServer.getPluginConfigManager();
- boolean skipPostOperation = false;
-
-
- // Start the processing timer.
- processingStartTime = System.currentTimeMillis();
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- return;
- }
-
-
- // Create a labeled block of code that we can break out of if a problem is
- // detected.
-deleteProcessing:
- {
- // Invoke the pre-parse delete plugins.
- PreParsePluginResult preParseResult =
- pluginConfigManager.invokePreParseDeletePlugins(this);
- if (preParseResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the request and
- // result and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logDeleteRequest(this);
- logDeleteResponse(this);
- pluginConfigManager.invokePostResponseDeletePlugins(this);
- return;
- }
- else if (preParseResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- logDeleteRequest(this);
- break deleteProcessing;
- }
- else if (preParseResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break deleteProcessing;
- }
-
-
- // Log the delete request message.
- logDeleteRequest(this);
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logDeleteResponse(this);
- pluginConfigManager.invokePostResponseDeletePlugins(this);
- return;
- }
-
-
- // Process the entry DN to convert it from its raw form as provided by the
- // client to the form required for the rest of the delete processing.
- try
- {
- if (entryDN == null)
- {
- entryDN = DN.decode(rawEntryDN);
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break deleteProcessing;
- }
-
-
- // Grab a write lock on the entry.
- Lock entryLock = null;
- for (int i=0; i < 3; i++)
- {
- entryLock = LockManager.lockWrite(entryDN);
- if (entryLock != null)
- {
- break;
- }
- }
-
- if (entryLock == null)
- {
- setResultCode(DirectoryServer.getServerErrorResultCode());
- appendErrorMessage(getMessage(MSGID_DELETE_CANNOT_LOCK_ENTRY,
- String.valueOf(entryDN)));
- break deleteProcessing;
- }
-
-
- try
- {
- // Get the entry to delete. If it doesn't exist, then fail.
- try
- {
- entry = DirectoryServer.getEntry(entryDN);
- if (entry == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_DELETE_NO_SUCH_ENTRY,
- String.valueOf(entryDN)));
-
- try
- {
- DN parentDN = entryDN.getParentDNInSuffix();
- while (parentDN != null)
- {
- if (DirectoryServer.entryExists(parentDN))
- {
- setMatchedDN(parentDN);
- break;
- }
-
- parentDN = parentDN.getParentDNInSuffix();
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
-
- break deleteProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
- break deleteProcessing;
- }
-
-
- // Invoke any conflict resolution processing that might be needed by the
- // synchronization provider.
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.handleConflictResolution(this);
- if (! result.continueOperationProcessing())
- {
- break deleteProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_DELETE_SYNCH_CONFLICT_RESOLUTION_FAILED,
- getConnectionID(), getOperationID(),
- getExceptionMessage(de));
-
- setResponseData(de);
- break deleteProcessing;
- }
- }
-
- // Check to see if the client has permission to perform the
- // delete.
-
- // Check to see if there are any controls in the request. If so, then
- // see if there is any special processing required.
- boolean noOp = false;
- LDAPPreReadRequestControl preReadRequest = null;
- List<Control> requestControls = getRequestControls();
- if ((requestControls != null) && (! requestControls.isEmpty()))
- {
- for (int i=0; i < requestControls.size(); i++)
- {
- Control c = requestControls.get(i);
- String oid = c.getOID();
-
- if (oid.equals(OID_LDAP_ASSERTION))
- {
- LDAPAssertionRequestControl assertControl;
- if (c instanceof LDAPAssertionRequestControl)
- {
- assertControl = (LDAPAssertionRequestControl) c;
- }
- else
- {
- try
- {
- assertControl = LDAPAssertionRequestControl.decodeControl(c);
- requestControls.set(i, assertControl);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break deleteProcessing;
- }
- }
-
- try
- {
- // FIXME -- We need to determine whether the current user has
- // permission to make this determination.
- SearchFilter filter = assertControl.getSearchFilter();
- if (! filter.matchesEntry(entry))
- {
- setResultCode(ResultCode.ASSERTION_FAILED);
-
- appendErrorMessage(getMessage(MSGID_DELETE_ASSERTION_FAILED,
- String.valueOf(entryDN)));
-
- break deleteProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(ResultCode.PROTOCOL_ERROR);
-
- int msgID = MSGID_DELETE_CANNOT_PROCESS_ASSERTION_FILTER;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- de.getErrorMessage()));
-
- break deleteProcessing;
- }
- }
- else if (oid.equals(OID_LDAP_NOOP_OPENLDAP_ASSIGNED))
- {
- noOp = true;
- }
- else if (oid.equals(OID_LDAP_READENTRY_PREREAD))
- {
- if (c instanceof LDAPAssertionRequestControl)
- {
- preReadRequest = (LDAPPreReadRequestControl) c;
- }
- else
- {
- try
- {
- preReadRequest = LDAPPreReadRequestControl.decodeControl(c);
- requestControls.set(i, preReadRequest);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break deleteProcessing;
- }
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V1))
- {
- // The requester must have the PROXIED_AUTH privilige in order to
- // be able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break deleteProcessing;
- }
-
-
- ProxiedAuthV1Control proxyControl;
- if (c instanceof ProxiedAuthV1Control)
- {
- proxyControl = (ProxiedAuthV1Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV1Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break deleteProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break deleteProcessing;
- }
-
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_DELETE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break deleteProcessing;
- }
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V2))
- {
- // The requester must have the PROXIED_AUTH privilige in order to
- // be able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break deleteProcessing;
- }
-
-
- ProxiedAuthV2Control proxyControl;
- if (c instanceof ProxiedAuthV2Control)
- {
- proxyControl = (ProxiedAuthV2Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV2Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break deleteProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break deleteProcessing;
- }
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_DELETE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break deleteProcessing;
- }
-
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
-
- // NYI -- Add support for additional controls.
- else if (c.isCritical())
- {
- Backend backend = DirectoryServer.getBackend(entryDN);
- if ((backend == null) || (! backend.supportsControl(oid)))
- {
- setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
-
- int msgID = MSGID_DELETE_UNSUPPORTED_CRITICAL_CONTROL;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- oid));
-
- break deleteProcessing;
- }
- }
- }
- }
-
-
- // FIXME: for now assume that this will check all permission
- // pertinent to the operation. This includes proxy authorization
- // and any other controls specified.
-
- // FIXME: earlier checks to see if the entry already exists may
- // have already exposed sensitive information to the client.
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isAllowed(this) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_DELETE_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break deleteProcessing;
- }
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logDeleteResponse(this);
- pluginConfigManager.invokePostResponseDeletePlugins(this);
- return;
- }
-
-
- // If the operation is not a synchronization operation,
- // invoke the pre-delete plugins.
- if (!isSynchronizationOperation())
- {
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationDeletePlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the request
- // and result and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
- logDeleteResponse(this);
- pluginConfigManager.invokePostResponseDeletePlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break deleteProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break deleteProcessing;
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logDeleteResponse(this);
- pluginConfigManager.invokePostResponseDeletePlugins(this);
- return;
- }
-
-
- // Get the backend to use for the delete. If there is none, then fail.
- Backend backend = DirectoryServer.getBackend(entryDN);
- if (backend == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_DELETE_NO_SUCH_ENTRY,
- String.valueOf(entryDN)));
- break deleteProcessing;
- }
-
-
- // If it is not a private backend, then check to see if the server or
- // backend is operating in read-only mode.
- if (! backend.isPrivateBackend())
- {
- switch (DirectoryServer.getWritabilityMode())
- {
- case DISABLED:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_DELETE_SERVER_READONLY,
- String.valueOf(entryDN)));
- break deleteProcessing;
-
- case INTERNAL_ONLY:
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_DELETE_SERVER_READONLY,
- String.valueOf(entryDN)));
- break deleteProcessing;
- }
- }
-
- switch (backend.getWritabilityMode())
- {
- case DISABLED:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_DELETE_BACKEND_READONLY,
- String.valueOf(entryDN)));
- break deleteProcessing;
-
- case INTERNAL_ONLY:
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_DELETE_BACKEND_READONLY,
- String.valueOf(entryDN)));
- break deleteProcessing;
- }
- }
- }
-
-
- // The selected backend will have the responsibility of making sure that
- // the entry actually exists and does not have any children (or possibly
- // handling a subtree delete). But we will need to check if there are
- // any subordinate backends that should stop us from attempting the
- // delete.
- Backend[] subBackends = backend.getSubordinateBackends();
- for (Backend b : subBackends)
- {
- DN[] baseDNs = b.getBaseDNs();
- for (DN dn : baseDNs)
- {
- if (dn.isDescendantOf(entryDN))
- {
- setResultCode(ResultCode.NOT_ALLOWED_ON_NONLEAF);
- appendErrorMessage(getMessage(MSGID_DELETE_HAS_SUB_BACKEND,
- String.valueOf(entryDN),
- String.valueOf(dn)));
- break deleteProcessing;
- }
- }
- }
-
-
- // Actually perform the delete.
- try
- {
- if (noOp)
- {
- appendErrorMessage(getMessage(MSGID_DELETE_NOOP));
-
- // FIXME -- We must set a result code other than SUCCESS.
- }
- else
- {
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.doPreOperation(this);
- if (! result.continueOperationProcessing())
- {
- break deleteProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_DELETE_SYNCH_PREOP_FAILED, getConnectionID(),
- getOperationID(), getExceptionMessage(de));
-
- setResponseData(de);
- break deleteProcessing;
- }
- }
-
- backend.deleteEntry(entryDN, this);
- }
-
- if (preReadRequest != null)
- {
- Entry entryCopy = entry.duplicate(true);
-
- if (! preReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- entryCopy.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! preReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- entryCopy.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! preReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- entryCopy.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // FIXME -- Check access controls on the entry to see if it should
- // be returned or if any attributes need to be stripped
- // out..
- SearchResultEntry searchEntry = new SearchResultEntry(entryCopy);
- LDAPPreReadResponseControl responseControl =
- new LDAPPreReadResponseControl(preReadRequest.getOID(),
- preReadRequest.isCritical(),
- searchEntry);
-
- responseControls.add(responseControl);
- }
-
- setResultCode(ResultCode.SUCCESS);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break deleteProcessing;
- }
- catch (CancelledOperationException coe)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, coe);
- }
-
- CancelResult cancelResult = coe.getCancelResult();
-
- setCancelResult(cancelResult);
- setResultCode(cancelResult.getResultCode());
-
- String message = coe.getMessage();
- if ((message != null) && (message.length() > 0))
- {
- appendErrorMessage(message);
- }
-
- break deleteProcessing;
- }
- }
- finally
- {
- LockManager.unlock(entryDN, entryLock);
-
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- provider.doPostOperation(this);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_DELETE_SYNCH_POSTOP_FAILED, getConnectionID(),
- getOperationID(), getExceptionMessage(de));
-
- setResponseData(de);
- break;
- }
- }
- }
- }
-
-
- // Indicate that it is now too late to attempt to cancel the operation.
- setCancelResult(CancelResult.TOO_LATE);
-
-
- // Invoke the post-operation delete plugins.
- if (! skipPostOperation)
- {
- PostOperationPluginResult postOperationResult =
- pluginConfigManager.invokePostOperationDeletePlugins(this);
- if (postOperationResult.connectionTerminated())
- {
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
- logDeleteResponse(this);
- pluginConfigManager.invokePostResponseDeletePlugins(this);
- return;
- }
- }
-
-
- // Notify any change notification listeners that might be registered with
- // the server.
- if (getResultCode() == ResultCode.SUCCESS)
- {
- for (ChangeNotificationListener changeListener :
- DirectoryServer.getChangeNotificationListeners())
- {
- try
- {
- changeListener.handleDeleteOperation(this, entry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_DELETE_ERROR_NOTIFYING_CHANGE_LISTENER;
- String message = getMessage(msgID, getExceptionMessage(e));
- logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
- }
- }
- }
-
-
- // Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
-
-
- // Send the delete response to the client.
- getClientConnection().sendResponse(this);
-
-
- // Log the delete response.
- logDeleteResponse(this);
-
-
- // Notify any persistent searches that might be registered with the server.
- if (getResultCode() == ResultCode.SUCCESS)
- {
- for (PersistentSearch persistentSearch :
- DirectoryServer.getPersistentSearches())
- {
- try
- {
- persistentSearch.processDelete(this, entry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_DELETE_ERROR_NOTIFYING_PERSISTENT_SEARCH;
- String message = getMessage(msgID, String.valueOf(persistentSearch),
- getExceptionMessage(e));
- logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
-
- DirectoryServer.deregisterPersistentSearch(persistentSearch);
- }
- }
- }
-
-
- // Invoke the post-response delete plugins.
- pluginConfigManager.invokePostResponseDeletePlugins(this);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelResult cancel(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
-
- CancelResult cancelResult = getCancelResult();
- long stopWaitingTime = System.currentTimeMillis() + 5000;
- while ((cancelResult == null) &&
- (System.currentTimeMillis() < stopWaitingTime))
- {
- try
- {
- Thread.sleep(50);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
-
- cancelResult = getCancelResult();
- }
-
- if (cancelResult == null)
- {
- // This can happen in some rare cases (e.g., if a client disconnects and
- // there is still a lot of data to send to that client), and in this case
- // we'll prevent the cancel thread from blocking for a long period of
- // time.
- cancelResult = CancelResult.CANNOT_CANCEL;
- }
-
- return cancelResult;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelRequest getCancelRequest()
- {
- return cancelRequest;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
- return true;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void toString(StringBuilder buffer)
- {
- buffer.append("DeleteOperation(connID=");
- buffer.append(clientConnection.getConnectionID());
- buffer.append(", opID=");
- buffer.append(operationID);
- buffer.append(", dn=");
- buffer.append(rawEntryDN);
- buffer.append(")");
- }
-}
-
+}
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperationBasis.java b/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperationBasis.java
new file mode 100644
index 0000000..a930178
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperationBasis.java
@@ -0,0 +1,671 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ENTRY_DN;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ERROR_MESSAGE;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_MATCHED_DN;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_PROCESSING_TIME;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_REFERRAL_URLS;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_RESULT_CODE;
+import static org.opends.server.loggers.AccessLogger.logDeleteRequest;
+import static org.opends.server.loggers.AccessLogger.logDeleteResponse;
+import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.messages.CoreMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.getExceptionMessage;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.plugin.PreParsePluginResult;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.ErrorLogCategory;
+import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.operation.PostResponseDeleteOperation;
+import org.opends.server.types.operation.PreParseDeleteOperation;
+import org.opends.server.workflowelement.localbackend.*;
+
+
+
+/**
+ * This class defines an operation that may be used to remove an entry from the
+ * Directory Server.
+ */
+public class DeleteOperationBasis
+ extends AbstractOperation
+ implements PreParseDeleteOperation,
+ DeleteOperation,
+ PostResponseDeleteOperation
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
+
+ // The raw, unprocessed entry DN as included in the client request.
+ private ByteString rawEntryDN;
+
+ // The cancel request that has been issued for this delete operation.
+ private CancelRequest cancelRequest;
+
+ // The DN of the entry for the delete operation.
+ private DN entryDN;
+
+ // The proxied authorization target DN for this operation.
+ private DN proxiedAuthorizationDN;
+
+ // The set of response controls for this delete operation.
+ private List<Control> responseControls;
+
+ // The change number that has been assigned to this operation.
+ private long changeNumber;
+
+
+ /**
+ * Creates a new delete operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param rawEntryDN The raw, unprocessed DN of the entry to delete,
+ * as included in the client request.
+ */
+ public DeleteOperationBasis(ClientConnection clientConnection,
+ long operationID,
+ int messageID, List<Control> requestControls,
+ ByteString rawEntryDN)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.rawEntryDN = rawEntryDN;
+
+ entryDN = null;
+ responseControls = new ArrayList<Control>();
+ cancelRequest = null;
+ changeNumber = -1;
+ }
+
+
+
+ /**
+ * Creates a new delete operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param entryDN The entry DN for this delete operation.
+ */
+ public DeleteOperationBasis(ClientConnection clientConnection,
+ long operationID,
+ int messageID, List<Control> requestControls,
+ DN entryDN)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.entryDN = entryDN;
+
+ rawEntryDN = new ASN1OctetString(entryDN.toString());
+ responseControls = new ArrayList<Control>();
+ cancelRequest = null;
+ changeNumber = -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ByteString getRawEntryDN()
+ {
+ return rawEntryDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawEntryDN(ByteString rawEntryDN)
+ {
+ this.rawEntryDN = rawEntryDN;
+
+ entryDN = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getEntryDN()
+ {
+ try
+ {
+ if (entryDN == null)
+ {
+ entryDN = DN.decode(rawEntryDN);
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResultCode(de.getResultCode());
+ appendErrorMessage(de.getErrorMessage());
+ setMatchedDN(de.getMatchedDN());
+ setReferralURLs(de.getReferralURLs());
+ }
+
+ return entryDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getChangeNumber()
+ {
+ return changeNumber;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setChangeNumber(long changeNumber)
+ {
+ this.changeNumber = changeNumber;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final OperationType getOperationType()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ return OperationType.DELETE;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message,
+ int messageID)
+ {
+ // Before calling clientConnection.disconnect, we need to mark this
+ // operation as cancelled so that the attempt to cancel it later won't cause
+ // an unnecessary delay.
+ setCancelResult(CancelResult.CANCELED);
+
+ clientConnection.disconnect(disconnectReason, sendNotification, message,
+ messageID);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final String[][] getRequestLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final String[][] getResponseLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ String resultCode = String.valueOf(getResultCode().getIntValue());
+
+ String errorMessage;
+ StringBuilder errorMessageBuffer = getErrorMessage();
+ if (errorMessageBuffer == null)
+ {
+ errorMessage = null;
+ }
+ else
+ {
+ errorMessage = errorMessageBuffer.toString();
+ }
+
+ String matchedDNStr;
+ DN matchedDN = getMatchedDN();
+ if (matchedDN == null)
+ {
+ matchedDNStr = null;
+ }
+ else
+ {
+ matchedDNStr = matchedDN.toString();
+ }
+
+ String referrals;
+ List<String> referralURLs = getReferralURLs();
+ if ((referralURLs == null) || referralURLs.isEmpty())
+ {
+ referrals = null;
+ }
+ else
+ {
+ StringBuilder buffer = new StringBuilder();
+ Iterator<String> iterator = referralURLs.iterator();
+ buffer.append(iterator.next());
+
+ while (iterator.hasNext())
+ {
+ buffer.append(", ");
+ buffer.append(iterator.next());
+ }
+
+ referrals = buffer.toString();
+ }
+
+ String processingTime =
+ String.valueOf(getProcessingTime());
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
+ new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
+ new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
+ new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
+ new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return proxiedAuthorizationDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final List<Control> getResponseControls()
+ {
+ return responseControls;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void addResponseControl(Control control)
+ {
+ responseControls.add(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void removeResponseControl(Control control)
+ {
+ responseControls.remove(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final CancelResult cancel(CancelRequest cancelRequest)
+ {
+ this.cancelRequest = cancelRequest;
+
+ CancelResult cancelResult = getCancelResult();
+ long stopWaitingTime = System.currentTimeMillis() + 5000;
+ while ((cancelResult == null) &&
+ (System.currentTimeMillis() < stopWaitingTime))
+ {
+ try
+ {
+ Thread.sleep(50);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+
+ cancelResult = getCancelResult();
+ }
+
+ if (cancelResult == null)
+ {
+ // This can happen in some rare cases (e.g., if a client disconnects and
+ // there is still a lot of data to send to that client), and in this case
+ // we'll prevent the cancel thread from blocking for a long period of
+ // time.
+ cancelResult = CancelResult.CANNOT_CANCEL;
+ }
+
+ return cancelResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final CancelRequest getCancelRequest()
+ {
+ return cancelRequest;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public
+ boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ this.cancelRequest = cancelRequest;
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void toString(StringBuilder buffer)
+ {
+ buffer.append("DeleteOperation(connID=");
+ buffer.append(clientConnection.getConnectionID());
+ buffer.append(", opID=");
+ buffer.append(operationID);
+ buffer.append(", dn=");
+ buffer.append(rawEntryDN);
+ buffer.append(")");
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+ {
+ this.proxiedAuthorizationDN = proxiedAuthorizationDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void run()
+ {
+ setResultCode(ResultCode.UNDEFINED);
+
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+ // Start the processing timer.
+ setProcessingStartTime();
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelRequest() != null)
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ return;
+ }
+
+ // Create a labeled block of code that we can break out of if a problem is
+ // detected.
+deleteProcessing:
+ {
+ // Invoke the pre-parse delete plugins.
+ PreParsePluginResult preParseResult =
+ pluginConfigManager.invokePreParseDeletePlugins(this);
+ if (preParseResult.connectionTerminated())
+ {
+ // There's no point in continuing with anything. Log the request and
+ // result and return.
+ setResultCode(ResultCode.CANCELED);
+
+ int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
+ appendErrorMessage(getMessage(msgID));
+
+ setProcessingStopTime();
+
+ logDeleteRequest(this);
+ logDeleteResponse(this);
+ pluginConfigManager.invokePostResponseDeletePlugins(this);
+ return;
+ }
+ else if (preParseResult.sendResponseImmediately())
+ {
+ logDeleteRequest(this);
+ break deleteProcessing;
+ }
+ else if (preParseResult.skipCoreProcessing())
+ {
+ break deleteProcessing;
+ }
+
+
+ // Log the delete request message.
+ logDeleteRequest(this);
+
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelRequest() != null)
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ logDeleteResponse(this);
+ pluginConfigManager.invokePostResponseDeletePlugins(this);
+ return;
+ }
+
+
+ // Process the entry DN to convert it from its raw form as provided by the
+ // client to the form required for the rest of the delete processing.
+ DN entryDN = getEntryDN();
+ if (entryDN == null){
+ break deleteProcessing;
+ }
+
+
+ // Retrieve the network group attached to the client connection
+ // and get a workflow to process the operation.
+ NetworkGroup ng = getClientConnection().getNetworkGroup();
+ Workflow workflow = ng.getWorkflowCandidate(entryDN);
+ if (workflow == null)
+ {
+ // We have found no workflow for the requested base DN, just return
+ // a no such entry result code and stop the processing.
+ updateOperationErrMsgAndResCode();
+ break deleteProcessing;
+ }
+ workflow.execute(this);
+ }
+
+ // Check for and handle a request to cancel this operation.
+ if ((getCancelRequest() != null) ||
+ (getCancelResult() == CancelResult.CANCELED))
+ {
+ if (getCancelRequest() != null){
+ indicateCancelled(getCancelRequest());
+ }
+ setProcessingStopTime();
+ logDeleteResponse(this);
+ invokePostResponsePlugins();
+ return;
+ }
+
+ // Indicate that it is now too late to attempt to cancel the operation.
+ setCancelResult(CancelResult.TOO_LATE);
+
+ // Stop the processing timer.
+ setProcessingStopTime();
+
+
+ // Send the delete response to the client.
+ getClientConnection().sendResponse(this);
+
+
+ // Log the delete response.
+ logDeleteResponse(this);
+
+ // Check wether there are local operations in attachments
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+ if (localOperations != null && (! localOperations.isEmpty())){
+ for (Object localOp : localOperations)
+ {
+ LocalBackendDeleteOperation localOperation =
+ (LocalBackendDeleteOperation)localOp;
+ // Notify any persistent searches that might be registered with the
+ // server.
+ if (getResultCode() == ResultCode.SUCCESS)
+ {
+ for (PersistentSearch persistentSearch :
+ DirectoryServer.getPersistentSearches())
+ {
+ try
+ {
+ persistentSearch.processDelete(localOperation,
+ localOperation.getEntryToDelete());
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ int msgID = MSGID_DELETE_ERROR_NOTIFYING_PERSISTENT_SEARCH;
+ String message = getMessage(msgID,
+ String.valueOf(persistentSearch),
+ getExceptionMessage(e));
+ logError(ErrorLogCategory.CORE_SERVER,
+ ErrorLogSeverity.SEVERE_ERROR,
+ message, msgID);
+
+ DirectoryServer.deregisterPersistentSearch(persistentSearch);
+ }
+ }
+ }
+
+ // Invoke the post-response delete plugins.
+ pluginConfigManager.invokePostResponseDeletePlugins(localOperation);
+ }
+ }
+ }
+
+ /**
+ * Updates the error message and the result code of the operation.
+ *
+ * This method is called because no workflows were found to process
+ * the operation.
+ */
+ private void updateOperationErrMsgAndResCode()
+ {
+ setResultCode(ResultCode.NO_SUCH_OBJECT);
+ appendErrorMessage(getMessage(MSGID_DELETE_NO_SUCH_ENTRY,
+ String.valueOf(getEntryDN())));
+ }
+
+ /**
+ * Execute the postResponseDeletePlugins.
+ */
+ private void invokePostResponsePlugins()
+ {
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+ // Check wether there are local operations in attachments
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+
+ if (localOperations != null && (! localOperations.isEmpty())){
+ for (Object localOp : localOperations)
+ {
+ LocalBackendDeleteOperation localOperation =
+ (LocalBackendDeleteOperation)localOp;
+ // Invoke the post-response delete plugins.
+ pluginConfigManager.invokePostResponseDeletePlugins(localOperation);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This method always returns null.
+ */
+ public Entry getEntryToDelete() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperationWrapper.java b/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperationWrapper.java
new file mode 100644
index 0000000..4858485
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DeleteOperationWrapper.java
@@ -0,0 +1,569 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.ResultCode;
+
+/**
+ * This abstract class wraps/decorates a given delete operation.
+ * This class will be extended by sub-classes to enhance the
+ * functionnality of the DeleteOperationBasis.
+ */
+public abstract class DeleteOperationWrapper implements DeleteOperation
+{
+ DeleteOperation delete;
+
+ /**
+ * Creates a new delete operation based on the provided delete operation.
+ *
+ * @param delete The delete operation to wrap
+ */
+ public DeleteOperationWrapper(DeleteOperation delete){
+ this.delete = delete;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addRequestControl(Control control)
+ {
+ delete.addRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addResponseControl(Control control)
+ {
+ delete.addResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendAdditionalLogMessage(String message)
+ {
+ delete.appendAdditionalLogMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendErrorMessage(String message)
+ {
+ delete.appendErrorMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult cancel(CancelRequest cancelRequest)
+ {
+ return delete.cancel(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message, int messageID)
+ {
+ delete.disconnectClient(disconnectReason, sendNotification,
+ message, messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean dontSynchronize()
+ {
+ return delete.dontSynchronize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getAdditionalLogMessage()
+ {
+ return delete.getAdditionalLogMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getAttachment(String name)
+ {
+ return delete.getAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<String, Object> getAttachments()
+ {
+ return delete.getAttachments();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getAuthorizationDN()
+ {
+ return delete.getAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry getAuthorizationEntry()
+ {
+ return delete.getAuthorizationEntry();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelRequest getCancelRequest()
+ {
+ return delete.getCancelRequest();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult getCancelResult()
+ {
+ return delete.getCancelResult();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClientConnection getClientConnection()
+ {
+ return delete.getClientConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getCommonLogElements()
+ {
+ return delete.getCommonLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getConnectionID()
+ {
+ return delete.getConnectionID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getEntryDN()
+ {
+ return delete.getEntryDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getErrorMessage()
+ {
+ return delete.getErrorMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getMatchedDN()
+ {
+ return delete.getMatchedDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMessageID()
+ {
+ return delete.getMessageID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getOperationID()
+ {
+ return delete.getOperationID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public OperationType getOperationType()
+ {
+ return delete.getOperationType();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStartTime()
+ {
+ return delete.getProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStopTime()
+ {
+ return delete.getProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingTime()
+ {
+ return delete.getProcessingTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString getRawEntryDN()
+ {
+ return delete.getRawEntryDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<String> getReferralURLs()
+ {
+ return delete.getReferralURLs();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getRequestControls()
+ {
+ return delete.getRequestControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getRequestLogElements()
+ {
+ return delete.getRequestLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getResponseControls()
+ {
+ return delete.getResponseControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getResponseLogElements()
+ {
+ return delete.getResponseLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultCode getResultCode()
+ {
+ return delete.getResultCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void indicateCancelled(CancelRequest cancelRequest)
+ {
+ delete.indicateCancelled(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isInternalOperation()
+ {
+ return delete.isInternalOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSynchronizationOperation()
+ {
+ return delete.isSynchronizationOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void operationCompleted()
+ {
+ delete.operationCompleted();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object removeAttachment(String name)
+ {
+ return delete.removeAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeRequestControl(Control control)
+ {
+ delete.removeRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeResponseControl(Control control)
+ {
+ delete.removeResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAdditionalLogMessage(StringBuilder additionalLogMessage)
+ {
+ delete.setAdditionalLogMessage(additionalLogMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object setAttachment(String name, Object value)
+ {
+ return delete.setAttachment(name, value);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttachments(Map<String, Object> attachments)
+ {
+ delete.setAttachments(attachments);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAuthorizationEntry(Entry authorizationEntry)
+ {
+ delete.setAuthorizationEntry(authorizationEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ return delete.setCancelRequest(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCancelResult(CancelResult cancelResult)
+ {
+ delete.setCancelResult(cancelResult);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDontSynchronize(boolean dontSynchronize)
+ {
+ delete.setDontSynchronize(dontSynchronize);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setErrorMessage(StringBuilder errorMessage)
+ {
+ delete.setErrorMessage(errorMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInternalOperation(boolean isInternalOperation)
+ {
+ delete.setInternalOperation(isInternalOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMatchedDN(DN matchedDN)
+ {
+ delete.setMatchedDN(matchedDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStartTime()
+ {
+ delete.setProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStopTime()
+ {
+ delete.setProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawEntryDN(ByteString rawEntryDN)
+ {
+ delete.setRawEntryDN(rawEntryDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setReferralURLs(List<String> referralURLs)
+ {
+ delete.setReferralURLs(referralURLs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResponseData(DirectoryException directoryException)
+ {
+ delete.setResponseData(directoryException);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResultCode(ResultCode resultCode)
+ {
+ delete.setResultCode(resultCode);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSynchronizationOperation(boolean isSynchronizationOperation)
+ {
+ delete.setSynchronizationOperation(isSynchronizationOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getChangeNumber()
+ {
+ return delete.getChangeNumber();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setChangeNumber(long changeNumber)
+ {
+ delete.setChangeNumber(changeNumber);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return delete.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void toString(StringBuilder buffer)
+ {
+ delete.toString(buffer);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return delete.getProxiedAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+ {
+ delete.setProxiedAuthorizationDN(proxiedAuthorizationDN);
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
index 40a99ee..3b741dd 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -101,6 +101,8 @@
import static org.opends.server.util.StaticUtils.*;
import static org.opends.server.util.Validator.*;
import com.sleepycat.je.JEVersion;
+import org.opends.server.workflowelement.WorkflowElement;
+import org.opends.server.workflowelement.localbackend.*;
@@ -1114,6 +1116,12 @@
// Initialize all the backends and their associated suffixes.
initializeBackends();
+ // A first set of workflows had been created in the registerBackend
+ // method. We now need to complete the workflow creation for the
+ // backends that were not registered through the registerBackend
+ // method (ie. cn=config and RootDSE).
+ createAndRegisterRemainingWorkflows();
+
// Check for and initialize user configured entry cache if any,
// if not stick with default entry cache initialized earlier.
entryCacheConfigManager.initializeEntryCache();
@@ -2251,6 +2259,102 @@
}
+ /**
+ * Deregister a workflow from a network group.
+ *
+ * In the first implementation, workflows are stored in the default network
+ * group.
+ *
+ * @param backend the backend which is handled by the workflows to
+ * deregister
+ */
+ private static void deregisterWorkflows(
+ Backend backend
+ )
+ {
+ // Get the default network group and deregister all the workflows
+ // being configured for the backend (reminder: there is one worklfow
+ // per base DN configured in the backend).
+ NetworkGroup defaultNetworkGroup = NetworkGroup.getDefaultNetworkGroup();
+ for (DN baseDN: backend.getBaseDNs())
+ {
+ defaultNetworkGroup.deregisterWorkflow (baseDN);
+ }
+ }
+
+
+ /**
+ * Create a workflow for the a backend then register the workflow
+ * with the appropriate network group.
+ *
+ * TODO implement the registration with the appropriate network group.
+ *
+ * @param backend the backend handled by the workflow
+ */
+ private static void createAndRegisterWorkflows(
+ Backend backend
+ )
+ {
+ // Create a root workflow element to encapsulate the backend
+ LocalBackendWorkflowElement rootWE =
+ new LocalBackendWorkflowElement(backend);
+
+ // Create a worklfow for each baseDN being configured
+ // in the backend and register the workflow with the network groups
+ for (DN curBaseDN: backend.getBaseDNs())
+ {
+ WorkflowImpl workflowImpl = new WorkflowImpl(
+ curBaseDN, (WorkflowElement) rootWE);
+ registerWorkflowInNetworkGroups(workflowImpl);
+ }
+ }
+
+
+ /**
+ * Register a workflow with the appropriate network groups.
+ *
+ * In the first implementation, the workflow is registered with the
+ * default network group only.
+ *
+ * TODO implement the registration with the appropriate network group.
+ *
+ * @param workflowImpl the workflow to register
+ */
+ private static void registerWorkflowInNetworkGroups(
+ WorkflowImpl workflowImpl
+ )
+ {
+ // Register first the workflow with the default network group
+ NetworkGroup defaultNetworkGroup = NetworkGroup.getDefaultNetworkGroup();
+ defaultNetworkGroup.registerWorkflow(workflowImpl);
+
+ // Now for each network group that exposes the baseDN of the workflow
+ // create an instance of the workflow and register it with the network
+ // group.
+ // TODO jdemendi - we need the network group configuration to configure
+ // the workflows per network group.
+ }
+
+
+ /**
+ * Create the workflows for the backends that were not registered through
+ * registerBackend method, nemely cn=config and RootDSE.
+ *
+ * TODO jdemendi - read the Workflow config and create them accordingly
+ *
+ * For the prototype: there is no configuration for the workflows.
+ * So we create one workflow per local backend, and we register it
+ * to the pool.
+ */
+ private void createAndRegisterRemainingWorkflows()
+ {
+ // Create a workflow for the cn=config backend
+ createAndRegisterWorkflows (configHandler);
+
+ // Create a workflows for the rootDSE backend
+ createAndRegisterWorkflows (rootDSEBackend);
+ }
+
/**
* Initializes the Directory Server group manager.
@@ -6006,6 +6110,15 @@
monitor.initializeMonitorProvider(null);
backend.setBackendMonitor(monitor);
registerMonitorProvider(monitor);
+
+ // FIXME jdemendi - temporary code: create one workflow for each
+ // base DN being configured in the backend. We should not rely on the
+ // backend registration to create and register workflows because
+ // a workflow can be created for different type of "backend", including
+ // remote lDAP server. Instead, we should create the workflows using
+ // the administration framework. We will be doing so as soon as we
+ // have a configuration section for the workflows.
+ createAndRegisterWorkflows (backend);
}
}
}
@@ -6032,6 +6145,13 @@
directoryServer.backends = newBackends;
+ // Delete all the workflows registered for the backend.
+ // FIXME jdemendi - This task should be performed in the scope of the
+ // administration framework. However the administration framework
+ // requires a configuration section for the workflows which we don't have
+ // as of today.
+ deregisterWorkflows (backend);
+
BackendMonitor monitor = backend.getBackendMonitor();
if (monitor != null)
{
@@ -7190,7 +7310,7 @@
* @throws DirectoryException If a problem prevents the operation from being
* added to the queue (e.g., the queue is full).
*/
- public static void enqueueRequest(Operation operation)
+ public static void enqueueRequest(AbstractOperation operation)
throws DirectoryException
{
// See if a bind is already in progress on the associated connection. If so
@@ -7236,7 +7356,7 @@
}
case EXTENDED:
- ExtendedOperation extOp = (ExtendedOperation) operation;
+ ExtendedOperation extOp = (ExtendedOperation) operation;
String requestOID = extOp.getRequestOID();
if (!((requestOID != null) &&
requestOID.equals(OID_START_TLS_REQUEST)))
@@ -7283,7 +7403,7 @@
case EXTENDED:
// We will only allow the password modify and StartTLS extended
// operations.
- ExtendedOperation extOp = (ExtendedOperation) operation;
+ ExtendedOperation extOp = (ExtendedOperation) operation;
String requestOID = extOp.getRequestOID();
if ((requestOID == null) ||
((! requestOID.equals(OID_PASSWORD_MODIFY_REQUEST)) &&
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/ExtendedOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/ExtendedOperation.java
index 8268157..a683fc1 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/ExtendedOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/ExtendedOperation.java
@@ -38,12 +38,12 @@
import org.opends.server.api.plugin.PreOperationPluginResult;
import org.opends.server.api.plugin.PreParsePluginResult;
import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.Control;
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
-import org.opends.server.types.Operation;
import org.opends.server.types.OperationType;
import org.opends.server.types.ResultCode;
import org.opends.server.types.operation.PostOperationExtendedOperation;
@@ -54,6 +54,8 @@
import static org.opends.server.core.CoreConstants.*;
import static org.opends.server.loggers.AccessLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
+
+import org.opends.server.loggers.debug.DebugLogger;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.DebugLogLevel;
import static org.opends.server.messages.CoreMessages.*;
@@ -67,17 +69,14 @@
* kind of task.
*/
public class ExtendedOperation
- extends Operation
+ extends AbstractOperation
implements PreParseExtendedOperation, PreOperationExtendedOperation,
PostOperationExtendedOperation, PostResponseExtendedOperation
{
/**
* The tracer object for the debug logger.
*/
- private static final DebugTracer TRACER = getTracer();
-
-
-
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
// The value for the request associated with this extended operation.
private ASN1OctetString requestValue;
@@ -94,12 +93,6 @@
// The set of response controls for this extended operation.
private List<Control> responseControls;
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
// The OID for the request associated with this extended operation.
private String requestOID;
@@ -245,40 +238,6 @@
}
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
-
/**
* {@inheritDoc}
*/
@@ -384,7 +343,7 @@
}
String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
+ String.valueOf(getProcessingTime());
return new String[][]
{
@@ -433,9 +392,12 @@
/**
- * {@inheritDoc}
+ * Performs the work of actually processing this operation. This
+ * should include all processing for the operation, including
+ * invoking plugins, logging messages, performing access control,
+ * managing synchronization, and any other work that might need to
+ * be done in the course of processing.
*/
- @Override()
public final void run()
{
setResultCode(ResultCode.UNDEFINED);
@@ -448,7 +410,7 @@
// Start the processing timer.
- processingStartTime = System.currentTimeMillis();
+ setProcessingStartTime();
// Check for and handle a request to cancel this operation.
@@ -458,7 +420,7 @@
requestOID.equals(OID_START_TLS_REQUEST)))
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
return;
}
}
@@ -480,7 +442,7 @@
int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logExtendedRequest(this);
logExtendedResponse(this);
@@ -511,7 +473,7 @@
requestOID.equals(OID_START_TLS_REQUEST)))
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
pluginConfigManager.invokePostResponseExtendedPlugins(this);
return;
}
@@ -586,7 +548,7 @@
int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logExtendedResponse(this);
pluginConfigManager.invokePostResponseExtendedPlugins(this);
@@ -611,7 +573,7 @@
requestOID.equals(OID_START_TLS_REQUEST)))
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
pluginConfigManager.invokePostResponseExtendedPlugins(this);
return;
}
@@ -641,7 +603,7 @@
int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logExtendedResponse(this);
pluginConfigManager.invokePostResponseExtendedPlugins(this);
@@ -651,7 +613,7 @@
// Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
// Send the response to the client, if it has not already been sent.
@@ -765,7 +727,7 @@
* {@inheritDoc}
*/
@Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
+ public boolean setCancelRequest(CancelRequest cancelRequest)
{
this.cancelRequest = cancelRequest;
return true;
@@ -787,5 +749,6 @@
buffer.append(requestOID);
buffer.append(")");
}
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java b/opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java
index fc9756a..c7a0416 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java
@@ -35,6 +35,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+
+import org.opends.server.workflowelement.localbackend.*;
import org.opends.server.admin.ClassPropertyDefinition;
import org.opends.server.admin.server.ConfigurationAddListener;
import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -598,9 +600,11 @@
SearchScope.WHOLE_SUBTREE,
DereferencePolicy.NEVER_DEREF_ALIASES,
0, 0, false, filter, null, null);
+ LocalBackendSearchOperation localSearch =
+ new LocalBackendSearchOperation(internalSearch);
try
{
- backend.search(internalSearch);
+ backend.search(localSearch);
}
catch (Exception e)
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java
index 22f41ef..9c01614 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyDNOperation.java
@@ -50,6 +50,7 @@
import org.opends.server.controls.ProxiedAuthV1Control;
import org.opends.server.controls.ProxiedAuthV2Control;
import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
@@ -68,7 +69,6 @@
import org.opends.server.types.LockManager;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
-import org.opends.server.types.Operation;
import org.opends.server.types.OperationType;
import org.opends.server.types.Privilege;
import org.opends.server.types.RDN;
@@ -86,6 +86,8 @@
import org.opends.server.types.DebugLogLevel;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
+
+import org.opends.server.loggers.debug.DebugLogger;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.messages.CoreMessages.*;
import static org.opends.server.messages.MessageHandler.*;
@@ -99,14 +101,14 @@
* in the Directory Server.
*/
public class ModifyDNOperation
- extends Operation
+ extends AbstractOperation
implements PreParseModifyDNOperation, PreOperationModifyDNOperation,
PostOperationModifyDNOperation, PostResponseModifyDNOperation
{
/**
* The tracer object for the debug logger.
*/
- private static final DebugTracer TRACER = getTracer();
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
// Indicates whether to delete the old RDN value from the entry.
private boolean deleteOldRDN;
@@ -150,12 +152,6 @@
// The change number that has been assigned to this operation.
private long changeNumber;
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
// The new RDN for the entry.
private RDN newRDN;
@@ -490,41 +486,6 @@
return newEntry;
}
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
-
/**
* Retrieves the change number that has been assigned to this operation.
*
@@ -671,7 +632,7 @@
}
String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
+ String.valueOf(getProcessingTime());
return new String[][]
{
@@ -734,9 +695,12 @@
/**
- * {@inheritDoc}
+ * Performs the work of actually processing this operation. This
+ * should include all processing for the operation, including
+ * invoking plugins, logging messages, performing access control,
+ * managing synchronization, and any other work that might need to
+ * be done in the course of processing.
*/
- @Override()
public final void run()
{
setResultCode(ResultCode.UNDEFINED);
@@ -749,14 +713,14 @@
// Start the processing timer.
- processingStartTime = System.currentTimeMillis();
+ setProcessingStartTime();
// Check for and handle a request to cancel this operation.
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
return;
}
@@ -777,7 +741,7 @@
int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logModifyDNRequest(this);
logModifyDNResponse(this);
@@ -805,7 +769,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logModifyDNResponse(this);
pluginConfigManager.invokePostResponseModifyDNPlugins(this);
return;
@@ -941,7 +905,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logModifyDNResponse(this);
pluginConfigManager.invokePostResponseModifyDNPlugins(this);
return;
@@ -1025,7 +989,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logModifyDNResponse(this);
pluginConfigManager.invokePostResponseModifyDNPlugins(this);
return;
@@ -1571,7 +1535,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logModifyDNResponse(this);
pluginConfigManager.invokePostResponseModifyDNPlugins(this);
return;
@@ -1599,7 +1563,7 @@
int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logModifyDNResponse(this);
pluginConfigManager.invokePostResponseModifyDNPlugins(this);
return;
@@ -1798,7 +1762,7 @@
if (cancelRequest != null)
{
indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logModifyDNResponse(this);
pluginConfigManager.invokePostResponseModifyDNPlugins(this);
return;
@@ -2078,7 +2042,7 @@
int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT;
appendErrorMessage(getMessage(msgID));
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
logModifyDNResponse(this);
pluginConfigManager.invokePostResponseModifyDNPlugins(this);
return;
@@ -2114,7 +2078,7 @@
// Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
// Send the modify DN response to the client.
@@ -2217,7 +2181,7 @@
* {@inheritDoc}
*/
@Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
+ public boolean setCancelRequest(CancelRequest cancelRequest)
{
this.cancelRequest = cancelRequest;
return true;
@@ -2250,5 +2214,6 @@
buffer.append(")");
}
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
index e9661d4..ab03679 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperation.java
@@ -26,244 +26,29 @@
*/
package org.opends.server.core;
-
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
import java.util.List;
-import java.util.concurrent.locks.Lock;
-import org.opends.server.api.AttributeSyntax;
-import org.opends.server.api.Backend;
-import org.opends.server.api.ChangeNotificationListener;
-import org.opends.server.api.ClientConnection;
-import org.opends.server.api.PasswordStorageScheme;
-import org.opends.server.api.SynchronizationProvider;
-import org.opends.server.api.plugin.PostOperationPluginResult;
-import org.opends.server.api.plugin.PreOperationPluginResult;
-import org.opends.server.api.plugin.PreParsePluginResult;
-import org.opends.server.controls.LDAPAssertionRequestControl;
-import org.opends.server.controls.LDAPPreReadRequestControl;
-import org.opends.server.controls.LDAPPreReadResponseControl;
-import org.opends.server.controls.LDAPPostReadRequestControl;
-import org.opends.server.controls.LDAPPostReadResponseControl;
-import org.opends.server.controls.ProxiedAuthV1Control;
-import org.opends.server.controls.ProxiedAuthV2Control;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.ldap.LDAPAttribute;
-import org.opends.server.protocols.ldap.LDAPModification;
-import org.opends.server.schema.AuthPasswordSyntax;
-import org.opends.server.schema.BooleanSyntax;
-import org.opends.server.schema.UserPasswordSyntax;
-import org.opends.server.types.AcceptRejectWarn;
-import org.opends.server.types.AccountStatusNotificationType;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
-import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.ByteString;
-import org.opends.server.types.CancelledOperationException;
-import org.opends.server.types.CancelRequest;
-import org.opends.server.types.CancelResult;
-import org.opends.server.types.Control;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DisconnectReason;
import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.LDAPException;
-import org.opends.server.types.LockManager;
+import org.opends.server.types.DirectoryException;
import org.opends.server.types.Modification;
-import org.opends.server.types.ModificationType;
import org.opends.server.types.Operation;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.Privilege;
import org.opends.server.types.RawModification;
-import org.opends.server.types.RDN;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.SynchronizationProviderResult;
-import org.opends.server.types.operation.PreParseModifyOperation;
-import org.opends.server.types.operation.PreOperationModifyOperation;
-import org.opends.server.types.operation.PostOperationModifyOperation;
-import org.opends.server.types.operation.PostResponseModifyOperation;
-
-import static org.opends.server.config.ConfigConstants.*;
-import static org.opends.server.core.CoreConstants.*;
-import static org.opends.server.loggers.AccessLogger.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-import static org.opends.server.messages.CoreMessages.*;
-import static org.opends.server.messages.MessageHandler.getMessage;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
-
/**
- * This class defines an operation that may be used to modify an entry in the
- * Directory Server.
+ * This interface defines an operation used to modify an entry in
+ * the Directory Server.
*/
-public class ModifyOperation
- extends Operation
- implements PreParseModifyOperation, PreOperationModifyOperation,
- PostOperationModifyOperation, PostResponseModifyOperation
+public interface ModifyOperation extends Operation
{
/**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- // The raw, unprocessed entry DN as included by the client request.
- private ByteString rawEntryDN;
-
- // The cancel request that has been issued for this modify operation.
- private CancelRequest cancelRequest;
-
- // The DN of the entry for the modify operation.
- private DN entryDN;
-
- // The proxied authorization target DN for this operation.
- private DN proxiedAuthorizationDN;
-
- // The current entry, before any changes are applied.
- private Entry currentEntry;
-
- // The modified entry that will be stored in the backend.
- private Entry modifiedEntry;
-
- // The set of clear-text current passwords (if any were provided).
- private List<AttributeValue> currentPasswords;
-
- // The set of clear-text new passwords (if any were provided).
- private List<AttributeValue> newPasswords;
-
- // The set of response controls for this modify operation.
- private List<Control> responseControls;
-
- // The raw, unprocessed set of modifications as included in the client
- // request.
- private List<RawModification> rawModifications;
-
- // The set of modifications for this modify operation.
- private List<Modification> modifications;
-
- // The change number that has been assigned to this operation.
- private long changeNumber;
-
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
-
-
- /**
- * Creates a new modify operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param rawEntryDN The raw, unprocessed DN of the entry to modify,
- * as included in the client request.
- * @param rawModifications The raw, unprocessed set of modifications for
- * this modify operation as included in the client
- * request.
- */
- public ModifyOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- ByteString rawEntryDN,
- List<RawModification> rawModifications)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.rawEntryDN = rawEntryDN;
- this.rawModifications = rawModifications;
-
- entryDN = null;
- modifications = null;
- currentEntry = null;
- modifiedEntry = null;
- responseControls = new ArrayList<Control>();
- cancelRequest = null;
- changeNumber = -1;
-
- currentPasswords = null;
- newPasswords = null;
- }
-
-
-
- /**
- * Creates a new modify operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param entryDN The entry DN for the modify operation.
- * @param modifications The set of modifications for this modify
- * operation.
- */
- public ModifyOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- DN entryDN, List<Modification> modifications)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.entryDN = entryDN;
- this.modifications = modifications;
-
- rawEntryDN = new ASN1OctetString(entryDN.toString());
-
- rawModifications = new ArrayList<RawModification>(modifications.size());
- for (Modification m : modifications)
- {
- rawModifications.add(new LDAPModification(m.getModificationType(),
- new LDAPAttribute(m.getAttribute())));
- }
-
- currentEntry = null;
- modifiedEntry = null;
- responseControls = new ArrayList<Control>();
- cancelRequest = null;
- changeNumber = -1;
-
- currentPasswords = null;
- newPasswords = null;
- }
-
-
-
- /**
* Retrieves the raw, unprocessed entry DN as included in the client request.
* The DN that is returned may or may not be a valid DN, since no validation
* will have been performed upon it.
*
* @return The raw, unprocessed entry DN as included in the client request.
*/
- public final ByteString getRawEntryDN()
- {
- return rawEntryDN;
- }
-
-
+ public abstract ByteString getRawEntryDN();
/**
* Specifies the raw, unprocessed entry DN as included in the client request.
@@ -272,14 +57,7 @@
* @param rawEntryDN The raw, unprocessed entry DN as included in the client
* request.
*/
- public final void setRawEntryDN(ByteString rawEntryDN)
- {
- this.rawEntryDN = rawEntryDN;
-
- entryDN = null;
- }
-
-
+ public abstract void setRawEntryDN(ByteString rawEntryDN);
/**
* Retrieves the DN of the entry to modify. This should not be called by
@@ -289,12 +67,7 @@
* @return The DN of the entry to modify, or <CODE>null</CODE> if the raw
* entry DN has not yet been processed.
*/
- public final DN getEntryDN()
- {
- return entryDN;
- }
-
-
+ public abstract DN getEntryDN();
/**
* Retrieves the set of raw, unprocessed modifications as included in the
@@ -305,12 +78,7 @@
* @return The set of raw, unprocessed modifications as included in the
* client request.
*/
- public final List<RawModification> getRawModifications()
- {
- return rawModifications;
- }
-
-
+ public abstract List<RawModification> getRawModifications();
/**
* Adds the provided modification to the set of raw modifications for this
@@ -319,28 +87,15 @@
* @param rawModification The modification to add to the set of raw
* modifications for this modify operation.
*/
- public final void addRawModification(RawModification rawModification)
- {
- rawModifications.add(rawModification);
-
- modifications = null;
- }
-
-
+ public abstract void addRawModification(RawModification rawModification);
/**
* Specifies the raw modifications for this modify operation.
*
* @param rawModifications The raw modifications for this modify operation.
*/
- public final void setRawModifications(List<RawModification> rawModifications)
- {
- this.rawModifications = rawModifications;
-
- modifications = null;
- }
-
-
+ public abstract void setRawModifications(
+ List<RawModification> rawModifications);
/**
* Retrieves the set of modifications for this modify operation. Its contents
@@ -350,12 +105,7 @@
* <CODE>null</CODE> if the modifications have not yet been
* processed.
*/
- public final List<Modification> getModifications()
- {
- return modifications;
- }
-
-
+ public abstract List<Modification> getModifications();
/**
* Adds the provided modification to the set of modifications to this modify
@@ -367,112 +117,8 @@
* @throws DirectoryException If an unexpected problem occurs while applying
* the modification to the entry.
*/
- public final void addModification(Modification modification)
- throws DirectoryException
- {
- modifiedEntry.applyModification(modification);
- modifications.add(modification);
- }
-
-
-
- /**
- * Retrieves the current entry before any modifications are applied. This
- * will not be available to pre-parse plugins.
- *
- * @return The current entry, or <CODE>null</CODE> if it is not yet
- * available.
- */
- public final Entry getCurrentEntry()
- {
- return currentEntry;
- }
-
-
-
- /**
- * Retrieves the modified entry that is to be written to the backend. This
- * will be available to pre-operation plugins, and if such a plugin does make
- * a change to this entry, then it is also necessary to add that change to
- * the set of modifications to ensure that the update will be consistent.
- *
- * @return The modified entry that is to be written to the backend, or
- * <CODE>null</CODE> if it is not yet available.
- */
- public final Entry getModifiedEntry()
- {
- return modifiedEntry;
- }
-
-
-
- /**
- * Retrieves the set of clear-text current passwords for the user, if
- * available. This will only be available if the modify operation contains
- * one or more delete elements that target the password attribute and provide
- * the values to delete in the clear. It will not be available to pre-parse
- * plugins.
- *
- * @return The set of clear-text current password values as provided in the
- * modify request, or <CODE>null</CODE> if there were none or this
- * information is not yet available.
- */
- public final List<AttributeValue> getCurrentPasswords()
- {
- return currentPasswords;
- }
-
-
-
- /**
- * Retrieves the set of clear-text new passwords for the user, if available.
- * This will only be available if the modify operation contains one or more
- * add or replace elements that target the password attribute and provide the
- * values in the clear. It will not be available to pre-parse plugins.
- *
- * @return The set of clear-text new passwords as provided in the modify
- * request, or <CODE>null</CODE> if there were none or this
- * information is not yet available.
- */
- public final List<AttributeValue> getNewPasswords()
- {
- return newPasswords;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
+ public abstract void addModification(Modification modification)
+ throws DirectoryException;
/**
* Retrieves the change number that has been assigned to this operation.
@@ -481,12 +127,7 @@
* if none has been assigned yet or if there is no applicable
* synchronization mechanism in place that uses change numbers.
*/
- public final long getChangeNumber()
- {
- return changeNumber;
- }
-
-
+ public abstract long getChangeNumber();
/**
* Specifies the change number that has been assigned to this operation by the
@@ -495,131 +136,7 @@
* @param changeNumber The change number that has been assigned to this
* operation by the synchronization mechanism.
*/
- public final void setChangeNumber(long changeNumber)
- {
- this.changeNumber = changeNumber;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void disconnectClient(DisconnectReason disconnectReason,
- boolean sendNotification, String message,
- int messageID)
- {
- // Before calling clientConnection.disconnect, we need to mark this
- // operation as cancelled so that the attempt to cancel it later won't cause
- // an unnecessary delay.
- setCancelResult(CancelResult.CANCELED);
-
- clientConnection.disconnect(disconnectReason, sendNotification, message,
- messageID);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final OperationType getOperationType()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- return OperationType.MODIFY;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final String[][] getRequestLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- return new String[][]
- {
- new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }
- };
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final String[][] getResponseLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- String resultCode = String.valueOf(getResultCode().getIntValue());
-
- String errorMessage;
- StringBuilder errorMessageBuffer = getErrorMessage();
- if (errorMessageBuffer == null)
- {
- errorMessage = null;
- }
- else
- {
- errorMessage = errorMessageBuffer.toString();
- }
-
- String matchedDNStr;
- DN matchedDN = getMatchedDN();
- if (matchedDN == null)
- {
- matchedDNStr = null;
- }
- else
- {
- matchedDNStr = matchedDN.toString();
- }
-
- String referrals;
- List<String> referralURLs = getReferralURLs();
- if ((referralURLs == null) || referralURLs.isEmpty())
- {
- referrals = null;
- }
- else
- {
- StringBuilder buffer = new StringBuilder();
- Iterator<String> iterator = referralURLs.iterator();
- buffer.append(iterator.next());
-
- while (iterator.hasNext())
- {
- buffer.append(", ");
- buffer.append(iterator.next());
- }
-
- referrals = buffer.toString();
- }
-
- String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
-
- return new String[][]
- {
- new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
- new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
- new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
- new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
- new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
- };
- }
-
-
+ public abstract void setChangeNumber(long changeNumber);
/**
* Retrieves the proxied authorization DN for this operation if proxied
@@ -629,2415 +146,17 @@
* authorization has been requested, or {@code null} if proxied
* authorization has not been requested.
*/
- public DN getProxiedAuthorizationDN()
- {
- return proxiedAuthorizationDN;
- }
-
-
+ public abstract DN getProxiedAuthorizationDN();
/**
- * {@inheritDoc}
+ * Set the proxied authorization DN for this operation if proxied
+ * authorization has been requested.
+ *
+ * @param proxiedAuthorizationDN
+ * The proxied authorization DN for this operation if proxied
+ * authorization has been requested, or {@code null} if proxied
+ * authorization has not been requested.
*/
- @Override()
- public final List<Control> getResponseControls()
- {
- return responseControls;
- }
+ public abstract void setProxiedAuthorizationDN(DN proxiedAuthorizationDN);
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void addResponseControl(Control control)
- {
- responseControls.add(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void removeResponseControl(Control control)
- {
- responseControls.remove(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void run()
- {
- setResultCode(ResultCode.UNDEFINED);
-
-
- // Get the plugin config manager that will be used for invoking plugins.
- PluginConfigManager pluginConfigManager =
- DirectoryServer.getPluginConfigManager();
- boolean skipPostOperation = false;
-
-
- // Start the processing timer.
- processingStartTime = System.currentTimeMillis();
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- return;
- }
-
-
- // Create a labeled block of code that we can break out of if a problem is
- // detected.
-modifyProcessing:
- {
- // Invoke the pre-parse modify plugins.
- PreParsePluginResult preParseResult =
- pluginConfigManager.invokePreParseModifyPlugins(this);
- if (preParseResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the request and
- // result and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logModifyRequest(this);
- logModifyResponse(this);
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- return;
- }
- else if (preParseResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- logModifyRequest(this);
- break modifyProcessing;
- }
- else if (preParseResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break modifyProcessing;
- }
-
-
- // Log the modify request message.
- logModifyRequest(this);
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logModifyResponse(this);
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- return;
- }
-
-
- // Process the entry DN to convert it from the raw form to the form
- // required for the rest of the modify processing.
- try
- {
- if (entryDN == null)
- {
- entryDN = DN.decode(rawEntryDN);
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- skipPostOperation = true;
-
- break modifyProcessing;
- }
-
-
- // Process the modifications to convert them from their raw form to the
- // form required for the rest of the modify processing.
- if (modifications == null)
- {
- modifications = new ArrayList<Modification>(rawModifications.size());
- for (RawModification m : rawModifications)
- {
- try
- {
- modifications.add(m.toModification());
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break modifyProcessing;
- }
- }
- }
-
- if (modifications.isEmpty())
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- appendErrorMessage(getMessage(MSGID_MODIFY_NO_MODIFICATIONS,
- String.valueOf(entryDN)));
- break modifyProcessing;
- }
-
-
- // If the user must change their password before doing anything else, and
- // if the target of the modify operation isn't the user's own entry, then
- // reject the request.
- if ((! isInternalOperation()) && clientConnection.mustChangePassword())
- {
- DN authzDN = getAuthorizationDN();
- if ((authzDN != null) && (! authzDN.equals(entryDN)))
- {
- // The user will not be allowed to do anything else before
- // the password gets changed.
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_MUST_CHANGE_PASSWORD;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logModifyResponse(this);
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- return;
- }
-
-
- // Acquire a write lock on the target entry.
- Lock entryLock = null;
- for (int i=0; i < 3; i++)
- {
- entryLock = LockManager.lockWrite(entryDN);
- if (entryLock != null)
- {
- break;
- }
- }
-
- if (entryLock == null)
- {
- setResultCode(DirectoryServer.getServerErrorResultCode());
- appendErrorMessage(getMessage(MSGID_MODIFY_CANNOT_LOCK_ENTRY,
- String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break modifyProcessing;
- }
-
-
- try
- {
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logModifyResponse(this);
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- return;
- }
-
-
- // Get the entry to modify. If it does not exist, then fail.
- try
- {
- currentEntry = DirectoryServer.getEntry(entryDN);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break modifyProcessing;
- }
-
- if (currentEntry == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_MODIFY_NO_SUCH_ENTRY,
- String.valueOf(entryDN)));
-
- // See if one of the entry's ancestors exists.
- DN parentDN = entryDN.getParentDNInSuffix();
- while (parentDN != null)
- {
- try
- {
- if (DirectoryServer.entryExists(parentDN))
- {
- setMatchedDN(parentDN);
- break;
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- break;
- }
-
- parentDN = parentDN.getParentDNInSuffix();
- }
-
- break modifyProcessing;
- }
-
- // Check to see if there are any controls in the request. If so, then
- // see if there is any special processing required.
- boolean noOp = false;
- LDAPPreReadRequestControl preReadRequest = null;
- LDAPPostReadRequestControl postReadRequest = null;
- List<Control> requestControls = getRequestControls();
- if ((requestControls != null) && (! requestControls.isEmpty()))
- {
- for (int i=0; i < requestControls.size(); i++)
- {
- Control c = requestControls.get(i);
- String oid = c.getOID();
-
- if (oid.equals(OID_LDAP_ASSERTION))
- {
- LDAPAssertionRequestControl assertControl;
- if (c instanceof LDAPAssertionRequestControl)
- {
- assertControl = (LDAPAssertionRequestControl) c;
- }
- else
- {
- try
- {
- assertControl = LDAPAssertionRequestControl.decodeControl(c);
- requestControls.set(i, assertControl);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break modifyProcessing;
- }
- }
-
- try
- {
- // FIXME -- We need to determine whether the current user has
- // permission to make this determination.
- SearchFilter filter = assertControl.getSearchFilter();
- if (! filter.matchesEntry(currentEntry))
- {
- setResultCode(ResultCode.ASSERTION_FAILED);
-
- appendErrorMessage(getMessage(MSGID_MODIFY_ASSERTION_FAILED,
- String.valueOf(entryDN)));
-
- break modifyProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(ResultCode.PROTOCOL_ERROR);
-
- int msgID = MSGID_MODIFY_CANNOT_PROCESS_ASSERTION_FILTER;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- de.getErrorMessage()));
-
- break modifyProcessing;
- }
- }
- else if (oid.equals(OID_LDAP_NOOP_OPENLDAP_ASSIGNED))
- {
- noOp = true;
- }
- else if (oid.equals(OID_LDAP_READENTRY_PREREAD))
- {
- if (c instanceof LDAPAssertionRequestControl)
- {
- preReadRequest = (LDAPPreReadRequestControl) c;
- }
- else
- {
- try
- {
- preReadRequest = LDAPPreReadRequestControl.decodeControl(c);
- requestControls.set(i, preReadRequest);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break modifyProcessing;
- }
- }
- }
- else if (oid.equals(OID_LDAP_READENTRY_POSTREAD))
- {
- if (c instanceof LDAPAssertionRequestControl)
- {
- postReadRequest = (LDAPPostReadRequestControl) c;
- }
- else
- {
- try
- {
- postReadRequest = LDAPPostReadRequestControl.decodeControl(c);
- requestControls.set(i, postReadRequest);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break modifyProcessing;
- }
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V1))
- {
- // The requester must have the PROXIED_AUTH privilige in order to
- // be able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break modifyProcessing;
- }
-
-
- ProxiedAuthV1Control proxyControl;
- if (c instanceof ProxiedAuthV1Control)
- {
- proxyControl = (ProxiedAuthV1Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV1Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break modifyProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break modifyProcessing;
- }
- if (AccessControlConfigManager.getInstance().
- getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_MODIFY_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break modifyProcessing;
- }
-
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V2))
- {
- // The requester must have the PROXIED_AUTH privilige in order to
- // be able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break modifyProcessing;
- }
-
-
- ProxiedAuthV2Control proxyControl;
- if (c instanceof ProxiedAuthV2Control)
- {
- proxyControl = (ProxiedAuthV2Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV2Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break modifyProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break modifyProcessing;
- }
-
- if (AccessControlConfigManager.getInstance().
- getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_MODIFY_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break modifyProcessing;
- }
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
-
- // NYI -- Add support for additional controls.
- else if (c.isCritical())
- {
- Backend backend = DirectoryServer.getBackend(entryDN);
- if ((backend == null) || (! backend.supportsControl(oid)))
- {
- setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
-
- int msgID = MSGID_MODIFY_UNSUPPORTED_CRITICAL_CONTROL;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- oid));
-
- break modifyProcessing;
- }
- }
- }
- }
-
-
- // Get the password policy state object for the entry that can be used
- // to perform any appropriate password policy processing. Also, see if
- // the entry is being updated by the end user or an administrator.
- PasswordPolicyState pwPolicyState;
- boolean selfChange = entryDN.equals(getAuthorizationDN());
- try
- {
- // FIXME -- Need a way to enable debug mode.
- pwPolicyState = new PasswordPolicyState(currentEntry, false, false);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break modifyProcessing;
- }
-
-
- // Create a duplicate of the entry and apply the changes to it.
- modifiedEntry = currentEntry.duplicate(false);
-
- if (! noOp)
- {
- // Invoke any conflict resolution processing that might be needed by
- // the synchronization provider.
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.handleConflictResolution(this);
- if (! result.continueOperationProcessing())
- {
- break modifyProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_MODIFY_SYNCH_CONFLICT_RESOLUTION_FAILED,
- getConnectionID(), getOperationID(),
- getExceptionMessage(de));
-
- setResponseData(de);
- break modifyProcessing;
- }
- }
- }
-
-
- // Declare variables used for password policy state processing.
- boolean passwordChanged = false;
- boolean currentPasswordProvided = false;
- boolean isEnabled = true;
- boolean enabledStateChanged = false;
- int numPasswords;
- if (currentEntry.hasAttribute(
- pwPolicyState.getPolicy().getPasswordAttribute()))
- {
- // It may actually have more than one, but we can't tell the
- // difference if the values are encoded, and its enough for our
- // purposes just to know that there is at least one.
- numPasswords = 1;
- }
- else
- {
- numPasswords = 0;
- }
-
-
- // If it's not an internal or synchronization operation, then iterate
- // through the set of modifications to see if a password is included in
- // the changes. If so, then add the appropriate state changes to the
- // set of modifications.
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- for (Modification m : modifications)
- {
- if (m.getAttribute().getAttributeType().equals(
- pwPolicyState.getPolicy().getPasswordAttribute()))
- {
- passwordChanged = true;
- if (! selfChange)
- {
- if (! clientConnection.hasPrivilege(Privilege.PASSWORD_RESET,
- this))
- {
- int msgID = MSGID_MODIFY_PWRESET_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
- break modifyProcessing;
- }
- }
-
- break;
- }
- }
- }
-
-
- for (Modification m : modifications)
- {
- Attribute a = m.getAttribute();
- AttributeType t = a.getAttributeType();
-
-
- // If the attribute type is marked "NO-USER-MODIFICATION" then fail
- // unless this is an internal operation or is related to
- // synchronization in some way.
- if (t.isNoUserModification())
- {
- if (! (isInternalOperation() || isSynchronizationOperation() ||
- m.isInternal()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_MODIFY_ATTR_IS_NO_USER_MOD,
- String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
- }
-
- // If the attribute type is marked "OBSOLETE" and the modification
- // is setting new values, then fail unless this is an internal
- // operation or is related to synchronization in some way.
- if (t.isObsolete())
- {
- if (a.hasValue() &&
- (m.getModificationType() != ModificationType.DELETE))
- {
- if (! (isInternalOperation() || isSynchronizationOperation() ||
- m.isInternal()))
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
- appendErrorMessage(getMessage(MSGID_MODIFY_ATTR_IS_OBSOLETE,
- String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
- }
- }
-
-
- // See if the attribute is one which controls the privileges available
- // for a user. If it is, then the client must have the
- // PRIVILEGE_CHANGE privilege.
- if (t.hasName(OP_ATTR_PRIVILEGE_NAME))
- {
- if (! clientConnection.hasPrivilege(Privilege.PRIVILEGE_CHANGE,
- this))
- {
- int msgID = MSGID_MODIFY_CHANGE_PRIVILEGE_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
- break modifyProcessing;
- }
- }
-
-
- // If the modification is updating the password attribute, then
- // perform any necessary password policy processing. This processing
- // should be skipped for synchronization operations.
- boolean isPassword
- = t.equals(pwPolicyState.getPolicy().getPasswordAttribute());
- if (isPassword && (!(isSynchronizationOperation())))
- {
- // If the attribute contains any options, then reject it. Passwords
- // will not be allowed to have options. Skipped for internal
- // operations.
- if(!isInternalOperation())
- {
- if (a.hasOptions())
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_PASSWORDS_CANNOT_HAVE_OPTIONS;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
-
-
- // If it's a self change, then see if that's allowed.
- if (selfChange &&
- (! pwPolicyState.getPolicy().allowUserPasswordChanges()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_NO_USER_PW_CHANGES;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
-
-
- // If we require secure password changes, then makes sure it's a
- // secure communication channel.
- if (pwPolicyState.getPolicy().requireSecurePasswordChanges() &&
- (! clientConnection.isSecure()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_REQUIRE_SECURE_CHANGES;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
-
-
- // If it's a self change and it's not been long enough since the
- // previous change, then reject it.
- if (selfChange && pwPolicyState.isWithinMinimumAge())
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_WITHIN_MINIMUM_AGE;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
- }
-
- // Check to see whether this will adding, deleting, or replacing
- // password values (increment doesn't make any sense for passwords).
- // Then perform the appropriate type of processing for that kind of
- // modification.
- boolean isAdd = false;
- LinkedHashSet<AttributeValue> pwValues = a.getValues();
- LinkedHashSet<AttributeValue> encodedValues =
- new LinkedHashSet<AttributeValue>();
- switch (m.getModificationType())
- {
- case ADD:
- case REPLACE:
- int passwordsToAdd = pwValues.size();
-
- if (m.getModificationType() == ModificationType.ADD)
- {
- numPasswords += passwordsToAdd;
- isAdd = true;
- }
- else
- {
- numPasswords = passwordsToAdd;
- }
- // If there were multiple password values provided, then make
- // sure that's OK.
-
- if (! isInternalOperation() &&
- ! pwPolicyState.getPolicy().allowExpiredPasswordChanges() &&
- (passwordsToAdd > 1))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_MULTIPLE_VALUES_NOT_ALLOWED;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
-
- // Iterate through the password values and see if any of them
- // are pre-encoded. If so, then check to see if we'll allow it.
- // Otherwise, store the clear-text values for later validation
- // and update the attribute with the encoded values.
- for (AttributeValue v : pwValues)
- {
- if (pwPolicyState.passwordIsPreEncoded(v.getValue()))
- {
- if ((!isInternalOperation()) &&
- ! pwPolicyState.getPolicy().allowPreEncodedPasswords())
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_NO_PREENCODED_PASSWORDS;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
- else
- {
- encodedValues.add(v);
- }
- }
- else
- {
- if (isAdd)
- {
- // Make sure that the password value doesn't already
- // exist.
- if (pwPolicyState.passwordMatches(v.getValue()))
- {
- setResultCode(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS);
-
- int msgID = MSGID_MODIFY_PASSWORD_EXISTS;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
- }
-
- if (newPasswords == null)
- {
- newPasswords = new LinkedList<AttributeValue>();
- }
-
- newPasswords.add(v);
-
- try
- {
- for (ByteString s :
- pwPolicyState.encodePassword(v.getValue()))
- {
- encodedValues.add(new AttributeValue(
- a.getAttributeType(), s));
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- break modifyProcessing;
- }
- }
- }
-
- a.setValues(encodedValues);
-
- break;
-
- case DELETE:
- // Iterate through the password values and see if any of them
- // are pre-encoded. We will never allow pre-encoded passwords
- // for user password changes, but we will allow them for
- // administrators. For each clear-text value, verify that at
- // least one value in the entry matches and replace the
- // clear-text value with the appropriate encoded forms.
- for (AttributeValue v : pwValues)
- {
- if (pwPolicyState.passwordIsPreEncoded(v.getValue()))
- {
- if ((!isInternalOperation()) && selfChange)
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_NO_PREENCODED_PASSWORDS;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
- else
- {
- encodedValues.add(v);
- }
- }
- else
- {
- List<Attribute> attrList = currentEntry.getAttribute(t);
- if ((attrList == null) || (attrList.isEmpty()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_NO_EXISTING_VALUES;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
- boolean found = false;
- for (Attribute attr : attrList)
- {
- for (AttributeValue av : attr.getValues())
- {
- if (pwPolicyState.getPolicy().usesAuthPasswordSyntax())
- {
- if (AuthPasswordSyntax.isEncoded(av.getValue()))
- {
- try
- {
- StringBuilder[] compoenents =
- AuthPasswordSyntax.decodeAuthPassword(
- av.getStringValue());
- PasswordStorageScheme scheme =
- DirectoryServer.
- getAuthPasswordStorageScheme(
- compoenents[0].toString());
- if (scheme != null)
- {
- if (scheme.authPasswordMatches(
- v.getValue(),
- compoenents[1].toString(),
- compoenents[2].toString()))
- {
- encodedValues.add(av);
- found = true;
- }
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
-
- int msgID = MSGID_MODIFY_CANNOT_DECODE_PW;
- appendErrorMessage(
- getMessage(msgID, de.getErrorMessage()));
- break modifyProcessing;
- }
- }
- else
- {
- if (av.equals(v))
- {
- encodedValues.add(v);
- found = true;
- }
- }
- }
- else
- {
- if (UserPasswordSyntax.isEncoded(av.getValue()))
- {
- try
- {
- String[] compoenents =
- UserPasswordSyntax.decodeUserPassword(
- av.getStringValue());
- PasswordStorageScheme scheme =
- DirectoryServer.getPasswordStorageScheme(
- toLowerCase(compoenents[0]));
- if (scheme != null)
- {
- if (scheme.passwordMatches(
- v.getValue(),
- new ASN1OctetString(compoenents[1])))
- {
- encodedValues.add(av);
- found = true;
- }
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
-
- int msgID = MSGID_MODIFY_CANNOT_DECODE_PW;
- appendErrorMessage(getMessage(msgID,
- de.getErrorMessage()));
- break modifyProcessing;
- }
- }
- else
- {
- if (av.equals(v))
- {
- encodedValues.add(v);
- found = true;
- }
- }
- }
- }
- }
-
- if (found)
- {
- if (currentPasswords == null)
- {
- currentPasswords = new LinkedList<AttributeValue>();
- }
- currentPasswords.add(v);
-
- numPasswords--;
- }
- else
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_INVALID_PASSWORD;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
-
- currentPasswordProvided = true;
- }
- }
-
- a.setValues(encodedValues);
-
- break;
-
- default:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_INVALID_MOD_TYPE_FOR_PASSWORD;
- appendErrorMessage(getMessage(msgID,
- String.valueOf(m.getModificationType()), a.getName()));
-
- break modifyProcessing;
- }
- }
- else
- {
- // See if it's an attribute used to maintain the account
- // enabled/disabled state.
- AttributeType disabledAttr =
- DirectoryServer.getAttributeType(OP_ATTR_ACCOUNT_DISABLED,
- true);
- if (t.equals(disabledAttr))
- {
- enabledStateChanged = true;
- for (AttributeValue v : a.getValues())
- {
- try
- {
- isEnabled = (! BooleanSyntax.decodeBooleanValue(
- v.getNormalizedValue()));
- }
- catch (DirectoryException de)
- {
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
-
- int msgID = MSGID_MODIFY_INVALID_DISABLED_VALUE;
- String message =
- getMessage(msgID, OP_ATTR_ACCOUNT_DISABLED,
- String.valueOf(de.getErrorMessage()));
- appendErrorMessage(message);
- break modifyProcessing;
- }
- }
- }
- }
-
-
- switch (m.getModificationType())
- {
- case ADD:
- // Make sure that one or more values have been provided for the
- // attribute.
- LinkedHashSet<AttributeValue> newValues = a.getValues();
- if ((newValues == null) || newValues.isEmpty())
- {
- setResultCode(ResultCode.PROTOCOL_ERROR);
- appendErrorMessage(getMessage(MSGID_MODIFY_ADD_NO_VALUES,
- String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
-
-
- // Make sure that all the new values are valid according to the
- // associated syntax.
- if (DirectoryServer.checkSchema())
- {
- AcceptRejectWarn syntaxPolicy =
- DirectoryServer.getSyntaxEnforcementPolicy();
- AttributeSyntax syntax = t.getSyntax();
-
- if (syntaxPolicy == AcceptRejectWarn.REJECT)
- {
- StringBuilder invalidReason = new StringBuilder();
-
- for (AttributeValue v : newValues)
- {
- if (! syntax.valueIsAcceptable(v.getValue(), invalidReason))
- {
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
-
- int msgID = MSGID_MODIFY_ADD_INVALID_SYNTAX;
- appendErrorMessage(getMessage(msgID,
- String.valueOf(entryDN),
- a.getName(),
- v.getStringValue(),
- invalidReason.toString()));
-
- break modifyProcessing;
- }
- }
- }
- else if (syntaxPolicy == AcceptRejectWarn.WARN)
- {
- StringBuilder invalidReason = new StringBuilder();
-
- for (AttributeValue v : newValues)
- {
- if (! syntax.valueIsAcceptable(v.getValue(), invalidReason))
- {
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
-
- int msgID = MSGID_MODIFY_ADD_INVALID_SYNTAX;
- logError(ErrorLogCategory.SCHEMA,
- ErrorLogSeverity.SEVERE_WARNING, msgID,
- String.valueOf(entryDN), a.getName(),
- v.getStringValue(), invalidReason.toString());
-
- invalidReason = new StringBuilder();
- }
- }
- }
- }
-
-
- // Add the provided attribute or merge an existing attribute with
- // the values of the new attribute. If there are any duplicates,
- // then fail.
- LinkedList<AttributeValue> duplicateValues =
- new LinkedList<AttributeValue>();
- if (a.getAttributeType().isObjectClassType())
- {
- try
- {
- modifiedEntry.addObjectClasses(newValues);
- break;
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResponseData(de);
- break modifyProcessing;
- }
- }
- else
- {
- modifiedEntry.addAttribute(a, duplicateValues);
- if (duplicateValues.isEmpty())
- {
- break;
- }
- else
- {
- StringBuilder buffer = new StringBuilder();
- Iterator<AttributeValue> iterator =
- duplicateValues.iterator();
- buffer.append(iterator.next().getStringValue());
- while (iterator.hasNext())
- {
- buffer.append(", ");
- buffer.append(iterator.next().getStringValue());
- }
-
- setResultCode(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS);
-
- int msgID = MSGID_MODIFY_ADD_DUPLICATE_VALUE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName(),
- buffer.toString()));
-
- break modifyProcessing;
- }
- }
-
-
- case DELETE:
- // Remove the specified attribute values or the entire attribute
- // from the value. If there are any specified values that were
- // not present, then fail. If the RDN attribute value would be
- // removed, then fail.
- LinkedList<AttributeValue> missingValues =
- new LinkedList<AttributeValue>();
- boolean attrExists =
- modifiedEntry.removeAttribute(a, missingValues);
-
- if (attrExists)
- {
- if (missingValues.isEmpty())
- {
- RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, a.getOptions(),
- rdn.getAttributeValue(t))))
- {
- setResultCode(ResultCode.NOT_ALLOWED_ON_RDN);
-
- int msgID = MSGID_MODIFY_DELETE_RDN_ATTR;
- appendErrorMessage(getMessage(msgID,
- String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
-
- break;
- }
- else
- {
- StringBuilder buffer = new StringBuilder();
- Iterator<AttributeValue> iterator = missingValues.iterator();
- buffer.append(iterator.next().getStringValue());
- while (iterator.hasNext())
- {
- buffer.append(", ");
- buffer.append(iterator.next().getStringValue());
- }
-
- setResultCode(ResultCode.NO_SUCH_ATTRIBUTE);
-
- int msgID = MSGID_MODIFY_DELETE_MISSING_VALUES;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName(),
- buffer.toString()));
-
- break modifyProcessing;
- }
- }
- else
- {
- setResultCode(ResultCode.NO_SUCH_ATTRIBUTE);
-
- int msgID = MSGID_MODIFY_DELETE_NO_SUCH_ATTR;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
-
-
- case REPLACE:
- // If it is the objectclass attribute, then treat that separately.
- if (a.getAttributeType().isObjectClassType())
- {
- try
- {
- modifiedEntry.setObjectClasses(a.getValues());
- break;
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResponseData(de);
- break modifyProcessing;
- }
- }
-
-
- // If the provided attribute does not have any values, then we
- // will simply remove the attribute from the entry (if it exists).
- if (! a.hasValue())
- {
- modifiedEntry.removeAttribute(t, a.getOptions());
- RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, a.getOptions(),
- rdn.getAttributeValue(t))))
- {
- setResultCode(ResultCode.NOT_ALLOWED_ON_RDN);
-
- int msgID = MSGID_MODIFY_DELETE_RDN_ATTR;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
- break;
- }
-
-
- // Make sure that all the new values are valid according to the
- // associated syntax.
- newValues = a.getValues();
- if (DirectoryServer.checkSchema())
- {
- AcceptRejectWarn syntaxPolicy =
- DirectoryServer.getSyntaxEnforcementPolicy();
- AttributeSyntax syntax = t.getSyntax();
-
- if (syntaxPolicy == AcceptRejectWarn.REJECT)
- {
- StringBuilder invalidReason = new StringBuilder();
-
- for (AttributeValue v : newValues)
- {
- if (! syntax.valueIsAcceptable(v.getValue(), invalidReason))
- {
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
-
- int msgID = MSGID_MODIFY_REPLACE_INVALID_SYNTAX;
- appendErrorMessage(getMessage(msgID,
- String.valueOf(entryDN),
- a.getName(),
- v.getStringValue(),
- invalidReason.toString()));
-
- break modifyProcessing;
- }
- }
- }
- else if (syntaxPolicy == AcceptRejectWarn.WARN)
- {
- StringBuilder invalidReason = new StringBuilder();
-
- for (AttributeValue v : newValues)
- {
- if (! syntax.valueIsAcceptable(v.getValue(), invalidReason))
- {
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
-
- int msgID = MSGID_MODIFY_REPLACE_INVALID_SYNTAX;
- logError(ErrorLogCategory.SCHEMA,
- ErrorLogSeverity.SEVERE_WARNING, msgID,
- String.valueOf(entryDN), a.getName(),
- v.getStringValue(), invalidReason.toString());
-
- invalidReason = new StringBuilder();
- }
- }
- }
- }
-
-
- // If the provided attribute does not have any options, then we
- // will simply use it in place of any existing attribute of the
- // provided type (or add it if it doesn't exist).
- if (! a.hasOptions())
- {
- List<Attribute> attrList = new ArrayList<Attribute>(1);
- attrList.add(a);
- modifiedEntry.putAttribute(t, attrList);
-
- RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, a.getOptions(),
- rdn.getAttributeValue(t))))
- {
- setResultCode(ResultCode.NOT_ALLOWED_ON_RDN);
-
- int msgID = MSGID_MODIFY_DELETE_RDN_ATTR;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
- break;
- }
-
-
- // See if there is an existing attribute of the provided type. If
- // not, then we'll use the new one.
- List<Attribute> attrList = modifiedEntry.getAttribute(t);
- if ((attrList == null) || attrList.isEmpty())
- {
- attrList = new ArrayList<Attribute>(1);
- attrList.add(a);
- modifiedEntry.putAttribute(t, attrList);
-
- RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, a.getOptions(),
- rdn.getAttributeValue(t))))
- {
- setResultCode(ResultCode.NOT_ALLOWED_ON_RDN);
-
- int msgID = MSGID_MODIFY_DELETE_RDN_ATTR;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
- break;
- }
-
-
- // There must be an existing occurrence of the provided attribute
- // in the entry. If there is a version with exactly the set of
- // options provided, then replace it. Otherwise, add a new one.
- boolean found = false;
- for (int i=0; i < attrList.size(); i++)
- {
- if (attrList.get(i).optionsEqual(a.getOptions()))
- {
- attrList.set(i, a);
- found = true;
- break;
- }
- }
-
- if (! found)
- {
- attrList.add(a);
- }
-
- RDN rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t) &&
- (! modifiedEntry.hasValue(t, a.getOptions(),
- rdn.getAttributeValue(t))))
- {
- setResultCode(ResultCode.NOT_ALLOWED_ON_RDN);
-
- int msgID = MSGID_MODIFY_DELETE_RDN_ATTR;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
- break;
-
-
- case INCREMENT:
- // The specified attribute type must not be an RDN attribute.
- rdn = modifiedEntry.getDN().getRDN();
- if ((rdn != null) && rdn.hasAttributeType(t))
- {
- setResultCode(ResultCode.NOT_ALLOWED_ON_RDN);
- appendErrorMessage(getMessage(MSGID_MODIFY_INCREMENT_RDN,
- String.valueOf(entryDN),
- a.getName()));
- }
-
-
- // The provided attribute must have a single value, and it must be
- // an integer.
- LinkedHashSet<AttributeValue> values = a.getValues();
- if ((values == null) || values.isEmpty())
- {
- setResultCode(ResultCode.PROTOCOL_ERROR);
-
- int msgID = MSGID_MODIFY_INCREMENT_REQUIRES_VALUE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
-
- break modifyProcessing;
- }
- else if (values.size() > 1)
- {
- setResultCode(ResultCode.PROTOCOL_ERROR);
-
- int msgID = MSGID_MODIFY_INCREMENT_REQUIRES_SINGLE_VALUE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
- break modifyProcessing;
- }
-
- AttributeValue v = values.iterator().next();
-
- long incrementValue;
- try
- {
- incrementValue = Long.parseLong(v.getNormalizedStringValue());
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
-
- int msgID = MSGID_MODIFY_INCREMENT_PROVIDED_VALUE_NOT_INTEGER;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName(), v.getStringValue()));
-
- break modifyProcessing;
- }
-
-
- // Get the corresponding attribute from the entry and make sure
- // that it has a single integer value.
- attrList = modifiedEntry.getAttribute(t, a.getOptions());
- if ((attrList == null) || attrList.isEmpty())
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_MODIFY_INCREMENT_REQUIRES_EXISTING_VALUE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
-
- break modifyProcessing;
- }
-
- boolean updated = false;
- for (Attribute attr : attrList)
- {
- LinkedHashSet<AttributeValue> valueList = attr.getValues();
- if ((valueList == null) || valueList.isEmpty())
- {
- continue;
- }
-
- LinkedHashSet<AttributeValue> newValueList =
- new LinkedHashSet<AttributeValue>(valueList.size());
- for (AttributeValue existingValue : valueList)
- {
- long newIntValue;
- try
- {
- long existingIntValue =
- Long.parseLong(existingValue.getStringValue());
- newIntValue = existingIntValue + incrementValue;
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
-
- int msgID = MSGID_MODIFY_INCREMENT_REQUIRES_INTEGER_VALUE;
- appendErrorMessage(getMessage(msgID,
- String.valueOf(entryDN),
- a.getName(),
- existingValue.getStringValue()));
- break modifyProcessing;
- }
-
- ByteString newValue =
- new ASN1OctetString(String.valueOf(newIntValue));
- newValueList.add(new AttributeValue(t, newValue));
- }
-
- attr.setValues(newValueList);
- updated = true;
- }
-
- if (! updated)
- {
- setResultCode(ResultCode.CONSTRAINT_VIOLATION);
-
- int msgID = MSGID_MODIFY_INCREMENT_REQUIRES_EXISTING_VALUE;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN),
- a.getName()));
-
- break modifyProcessing;
- }
-
- break;
-
- default:
- }
- }
-
-
- // If there was a password change, then perform any additional checks
- // that may be necessary.
- if (passwordChanged)
- {
- // If it was a self change, then see if the current password was
- // provided and handle accordingly.
- if (selfChange &&
- pwPolicyState.getPolicy().requireCurrentPassword() &&
- (! currentPasswordProvided))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_PW_CHANGE_REQUIRES_CURRENT_PW;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
-
-
- // If this change would result in multiple password values, then see
- // if that's OK.
- if ((numPasswords > 1) &&
- (! pwPolicyState.getPolicy().allowMultiplePasswordValues()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_MULTIPLE_PASSWORDS_NOT_ALLOWED;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
-
-
- // If any of the password values should be validated, then do so now.
- if (selfChange ||
- (! pwPolicyState.getPolicy().skipValidationForAdministrators()))
- {
- if (newPasswords != null)
- {
- HashSet<ByteString> clearPasswords = new HashSet<ByteString>();
- clearPasswords.addAll(pwPolicyState.getClearPasswords());
-
- if (currentPasswords != null)
- {
- if (clearPasswords.isEmpty())
- {
- for (AttributeValue v : currentPasswords)
- {
- clearPasswords.add(v.getValue());
- }
- }
- else
- {
- // NOTE: We can't rely on the fact that Set doesn't allow
- // duplicates because technically it's possible that the
- // values aren't duplicates if they are ASN.1 elements with
- // different types (like 0x04 for a standard universal octet
- // string type versus 0x80 for a simple password in a bind
- // operation). So we have to manually check for duplicates.
- for (AttributeValue v : currentPasswords)
- {
- ByteString pw = v.getValue();
-
- boolean found = false;
- for (ByteString s : clearPasswords)
- {
- if (Arrays.equals(s.value(), pw.value()))
- {
- found = true;
- break;
- }
- }
-
- if (! found)
- {
- clearPasswords.add(pw);
- }
- }
- }
- }
-
- for (AttributeValue v : newPasswords)
- {
- StringBuilder invalidReason = new StringBuilder();
- if (! pwPolicyState.passwordIsAcceptable(this, modifiedEntry,
- v.getValue(),
- clearPasswords,
- invalidReason))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_PW_VALIDATION_FAILED;
- appendErrorMessage(getMessage(msgID,
- invalidReason.toString()));
- break modifyProcessing;
- }
- }
- }
- }
- }
-
-
- // Check to see if the client has permission to perform the
- // modify.
- // The access control check is not made any earlier because the
- // handler needs access to the modified entry.
-
- // FIXME: for now assume that this will check all permission
- // pertinent to the operation. This includes proxy authorization
- // and any other controls specified.
-
- // FIXME: earlier checks to see if the entry already exists may
- // have already exposed sensitive information to the client.
- if (!AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isAllowed(this)) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_MODIFY_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(entryDN)));
-
- skipPostOperation = true;
- break modifyProcessing;
- }
-
- boolean wasLocked = false;
- if (passwordChanged)
- {
- // See if the account was locked for any reason.
- wasLocked = pwPolicyState.lockedDueToIdleInterval() ||
- pwPolicyState.lockedDueToMaximumResetAge() ||
- pwPolicyState.lockedDueToFailures();
-
- // Update the password policy state attributes in the user's entry.
- // If the modification fails, then these changes won't be applied.
- pwPolicyState.setPasswordChangedTime();
- pwPolicyState.clearFailureLockout();
- pwPolicyState.clearGraceLoginTimes();
- pwPolicyState.clearWarnedTime();
-
- if(pwPolicyState.getPolicy().forceChangeOnAdd()
- || pwPolicyState.getPolicy().forceChangeOnReset())
- {
- if (selfChange)
- {
- pwPolicyState.setMustChangePassword(false);
- }
- else
- {
- pwPolicyState.setMustChangePassword(
- pwPolicyState.getPolicy().forceChangeOnReset());
- }
- }
-
- if (pwPolicyState.getPolicy().getRequireChangeByTime() > 0)
- {
- pwPolicyState.setRequiredChangeTime();
- }
- modifications.addAll(pwPolicyState.getModifications());
- //Apply pwd Policy modifications to modified entry.
- try {
- modifiedEntry.applyModifications(pwPolicyState.getModifications());
- } catch (DirectoryException e) {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- setResponseData(e);
- break modifyProcessing;
- }
- }
- else if ((! isInternalOperation()) &&
- pwPolicyState.mustChangePassword())
- {
- // The user will not be allowed to do anything else before
- // the password gets changed.
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
-
- int msgID = MSGID_MODIFY_MUST_CHANGE_PASSWORD;
- appendErrorMessage(getMessage(msgID));
- break modifyProcessing;
- }
-
- // Make sure that the new entry is valid per the server schema.
- if (DirectoryServer.checkSchema())
- {
- StringBuilder invalidReason = new StringBuilder();
- if (! modifiedEntry.conformsToSchema(null, false, false, false,
- invalidReason))
- {
- setResultCode(ResultCode.OBJECTCLASS_VIOLATION);
- appendErrorMessage(getMessage(MSGID_MODIFY_VIOLATES_SCHEMA,
- String.valueOf(entryDN),
- invalidReason.toString()));
- break modifyProcessing;
- }
- }
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logModifyResponse(this);
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- return;
- }
-
- // If the operation is not a synchronization operation,
- // Invoke the pre-operation modify plugins.
- if (!isSynchronizationOperation())
- {
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationModifyPlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result
- // and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logModifyResponse(this);
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break modifyProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break modifyProcessing;
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logModifyResponse(this);
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- return;
- }
-
-
- // Actually perform the modify operation. This should also include
- // taking care of any synchronization that might be needed.
- Backend backend = DirectoryServer.getBackend(entryDN);
- if (backend == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_MODIFY_NO_BACKEND_FOR_ENTRY,
- String.valueOf(entryDN)));
- break modifyProcessing;
- }
-
- try
- {
- // If it is not a private backend, then check to see if the server or
- // backend is operating in read-only mode.
- if (! backend.isPrivateBackend())
- {
- switch (DirectoryServer.getWritabilityMode())
- {
- case DISABLED:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_MODIFY_SERVER_READONLY,
- String.valueOf(entryDN)));
- break modifyProcessing;
-
- case INTERNAL_ONLY:
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_MODIFY_SERVER_READONLY,
- String.valueOf(entryDN)));
- break modifyProcessing;
- }
- }
-
- switch (backend.getWritabilityMode())
- {
- case DISABLED:
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_MODIFY_BACKEND_READONLY,
- String.valueOf(entryDN)));
- break modifyProcessing;
-
- case INTERNAL_ONLY:
- if (! (isInternalOperation() || isSynchronizationOperation()))
- {
- setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- appendErrorMessage(getMessage(MSGID_MODIFY_BACKEND_READONLY,
- String.valueOf(entryDN)));
- break modifyProcessing;
- }
- }
- }
-
-
- if (noOp)
- {
- appendErrorMessage(getMessage(MSGID_MODIFY_NOOP));
-
- // FIXME -- We must set a result code other than SUCCESS.
- }
- else
- {
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- SynchronizationProviderResult result =
- provider.doPreOperation(this);
- if (! result.continueOperationProcessing())
- {
- break modifyProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_MODIFY_SYNCH_PREOP_FAILED, getConnectionID(),
- getOperationID(), getExceptionMessage(de));
-
- setResponseData(de);
- break modifyProcessing;
- }
- }
-
- backend.replaceEntry(modifiedEntry, this);
-
-
- // If the modification was successful, then see if there's any other
- // work that we need to do here before handing off to postop
- // plugins.
- if (passwordChanged)
- {
- if (selfChange)
- {
- AuthenticationInfo authInfo =
- clientConnection.getAuthenticationInfo();
- if (authInfo.getAuthenticationDN().equals(entryDN))
- {
- clientConnection.setMustChangePassword(false);
- }
-
- int msgID = MSGID_MODIFY_PASSWORD_CHANGED;
- String message = getMessage(msgID);
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.PASSWORD_CHANGED, entryDN,
- msgID, message);
- }
- else
- {
- int msgID = MSGID_MODIFY_PASSWORD_RESET;
- String message = getMessage(msgID);
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.PASSWORD_RESET, entryDN,
- msgID, message);
- }
- }
-
- if (enabledStateChanged)
- {
- if (isEnabled)
- {
- int msgID = MSGID_MODIFY_ACCOUNT_ENABLED;
- String message = getMessage(msgID);
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_ENABLED, entryDN,
- msgID, message);
- }
- else
- {
- int msgID = MSGID_MODIFY_ACCOUNT_DISABLED;
- String message = getMessage(msgID);
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_DISABLED, entryDN,
- msgID, message);
- }
- }
-
- if (wasLocked)
- {
- int msgID = MSGID_MODIFY_ACCOUNT_UNLOCKED;
- String message = getMessage(msgID);
- pwPolicyState.generateAccountStatusNotification(
- AccountStatusNotificationType.ACCOUNT_UNLOCKED, entryDN,
- msgID, message);
- }
- }
-
- if (preReadRequest != null)
- {
- Entry entry = currentEntry.duplicate(true);
-
- if (! preReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- entry.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! preReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! preReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! preReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // FIXME -- Check access controls on the entry to see if it should
- // be returned or if any attributes need to be stripped
- // out..
- SearchResultEntry searchEntry = new SearchResultEntry(entry);
- LDAPPreReadResponseControl responseControl =
- new LDAPPreReadResponseControl(preReadRequest.getOID(),
- preReadRequest.isCritical(),
- searchEntry);
-
- responseControls.add(responseControl);
- }
-
- if (postReadRequest != null)
- {
- Entry entry = modifiedEntry.duplicate(true);
-
- if (! postReadRequest.allowsAttribute(
- DirectoryServer.getObjectClassAttributeType()))
- {
- entry.removeAttribute(
- DirectoryServer.getObjectClassAttributeType());
- }
-
- if (! postReadRequest.returnAllUserAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getUserAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- if (! postReadRequest.returnAllOperationalAttributes())
- {
- Iterator<AttributeType> iterator =
- entry.getOperationalAttributes().keySet().iterator();
- while (iterator.hasNext())
- {
- AttributeType attrType = iterator.next();
- if (! postReadRequest.allowsAttribute(attrType))
- {
- iterator.remove();
- }
- }
- }
-
- // FIXME -- Check access controls on the entry to see if it should
- // be returned or if any attributes need to be stripped
- // out..
- SearchResultEntry searchEntry = new SearchResultEntry(entry);
- LDAPPostReadResponseControl responseControl =
- new LDAPPostReadResponseControl(postReadRequest.getOID(),
- postReadRequest.isCritical(),
- searchEntry);
-
- responseControls.add(responseControl);
- }
-
- setResultCode(ResultCode.SUCCESS);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break modifyProcessing;
- }
- catch (CancelledOperationException coe)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, coe);
- }
-
- CancelResult cancelResult = coe.getCancelResult();
-
- setCancelResult(cancelResult);
- setResultCode(cancelResult.getResultCode());
-
- String message = coe.getMessage();
- if ((message != null) && (message.length() > 0))
- {
- appendErrorMessage(message);
- }
-
- break modifyProcessing;
- }
- }
- finally
- {
- LockManager.unlock(entryDN, entryLock);
-
- for (SynchronizationProvider provider :
- DirectoryServer.getSynchronizationProviders())
- {
- try
- {
- provider.doPostOperation(this);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- MSGID_MODIFY_SYNCH_POSTOP_FAILED, getConnectionID(),
- getOperationID(), getExceptionMessage(de));
-
- setResponseData(de);
- break;
- }
- }
- }
- }
-
-
- // Indicate that it is now too late to attempt to cancel the operation.
- setCancelResult(CancelResult.TOO_LATE);
-
-
- // Invoke the post-operation modify plugins.
- if (! skipPostOperation)
- {
- // FIXME -- Should this also be done while holding the locks?
- PostOperationPluginResult postOpResult =
- pluginConfigManager.invokePostOperationModifyPlugins(this);
- if (postOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the result and
- // return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logModifyResponse(this);
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- return;
- }
- }
-
-
- // Notify any change notification listeners that might be registered with
- // the server.
- if (getResultCode() == ResultCode.SUCCESS)
- {
- for (ChangeNotificationListener changeListener :
- DirectoryServer.getChangeNotificationListeners())
- {
- try
- {
- changeListener.handleModifyOperation(this, currentEntry,
- modifiedEntry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_MODIFY_ERROR_NOTIFYING_CHANGE_LISTENER;
- String message = getMessage(msgID, getExceptionMessage(e));
- logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
- }
- }
- }
-
-
- // Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
-
-
- // Send the modify response to the client.
- clientConnection.sendResponse(this);
-
-
- // Log the modify response.
- logModifyResponse(this);
-
-
- // Notify any persistent searches that might be registered with the server.
- if (getResultCode() == ResultCode.SUCCESS)
- {
- for (PersistentSearch persistentSearch :
- DirectoryServer.getPersistentSearches())
- {
- try
- {
- persistentSearch.processModify(this, currentEntry, modifiedEntry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_MODIFY_ERROR_NOTIFYING_PERSISTENT_SEARCH;
- String message = getMessage(msgID, String.valueOf(persistentSearch),
- getExceptionMessage(e));
- logError(ErrorLogCategory.CORE_SERVER, ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
-
- DirectoryServer.deregisterPersistentSearch(persistentSearch);
- }
- }
- }
-
-
- // Invoke the post-response modify plugins.
- pluginConfigManager.invokePostResponseModifyPlugins(this);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelResult cancel(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
-
- CancelResult cancelResult = getCancelResult();
- long stopWaitingTime = System.currentTimeMillis() + 5000;
- while ((cancelResult == null) &&
- (System.currentTimeMillis() < stopWaitingTime))
- {
- try
- {
- Thread.sleep(50);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
-
- cancelResult = getCancelResult();
- }
-
- if (cancelResult == null)
- {
- // This can happen in some rare cases (e.g., if a client disconnects and
- // there is still a lot of data to send to that client), and in this case
- // we'll prevent the cancel thread from blocking for a long period of
- // time.
- cancelResult = CancelResult.CANNOT_CANCEL;
- }
-
- return cancelResult;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelRequest getCancelRequest()
- {
- return cancelRequest;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
- return true;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void toString(StringBuilder buffer)
- {
- buffer.append("ModifyOperation(connID=");
- buffer.append(clientConnection.getConnectionID());
- buffer.append(", opID=");
- buffer.append(operationID);
- buffer.append(", dn=");
- buffer.append(rawEntryDN);
- buffer.append(")");
- }
-}
-
+}
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperationBasis.java b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperationBasis.java
new file mode 100644
index 0000000..f02b61f
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperationBasis.java
@@ -0,0 +1,773 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ENTRY_DN;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ERROR_MESSAGE;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_MATCHED_DN;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_PROCESSING_TIME;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_REFERRAL_URLS;
+import static org.opends.server.core.CoreConstants.LOG_ELEMENT_RESULT_CODE;
+import static org.opends.server.loggers.AccessLogger.logModifyRequest;
+import static org.opends.server.loggers.AccessLogger.logModifyResponse;
+import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.messages.CoreMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.getExceptionMessage;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.plugin.PreParsePluginResult;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.ldap.LDAPAttribute;
+import org.opends.server.types.LDAPException;
+import org.opends.server.protocols.ldap.LDAPModification;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.Entry;
+import org.opends.server.types.ErrorLogCategory;
+import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.Operation;
+import org.opends.server.types.RawModification;
+import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Modification;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.operation.PostResponseModifyOperation;
+import org.opends.server.types.operation.PreParseModifyOperation;
+import org.opends.server.workflowelement.localbackend.*;
+
+
+
+/**
+ * This class defines an operation that may be used to modify an entry in the
+ * Directory Server.
+ */
+public class ModifyOperationBasis
+ extends AbstractOperation implements ModifyOperation,
+ PreParseModifyOperation,
+ PostResponseModifyOperation
+ {
+
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
+
+ // The raw, unprocessed entry DN as included by the client request.
+ private ByteString rawEntryDN;
+
+ // The DN of the entry for the modify operation.
+ private DN entryDN;
+
+ // The proxied authorization target DN for this operation.
+ private DN proxiedAuthorizationDN;
+
+ // The set of response controls for this modify operation.
+ private List<Control> responseControls;
+
+ // The raw, unprocessed set of modifications as included in the client
+ // request.
+ private List<RawModification> rawModifications;
+
+ // The set of modifications for this modify operation.
+ private List<Modification> modifications;
+
+ // The cancel request that has been issued for this modify operation.
+ CancelRequest cancelRequest;
+
+ // The change number that has been assigned to this operation.
+ private long changeNumber;
+
+ /**
+ * Creates a new modify operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param rawEntryDN The raw, unprocessed DN of the entry to modify,
+ * as included in the client request.
+ * @param rawModifications The raw, unprocessed set of modifications for
+ * this modify operation as included in the client
+ * request.
+ */
+ public ModifyOperationBasis(ClientConnection clientConnection,
+ long operationID,
+ int messageID, List<Control> requestControls,
+ ByteString rawEntryDN,
+ List<RawModification> rawModifications)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.rawEntryDN = rawEntryDN;
+ this.rawModifications = rawModifications;
+
+ entryDN = null;
+ modifications = null;
+ responseControls = new ArrayList<Control>();
+ cancelRequest = null;
+ }
+
+ /**
+ * Creates a new modify operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param entryDN The entry DN for the modify operation.
+ * @param modifications The set of modifications for this modify
+ * operation.
+ */
+ public ModifyOperationBasis(ClientConnection clientConnection,
+ long operationID,
+ int messageID, List<Control> requestControls,
+ DN entryDN, List<Modification> modifications)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.entryDN = entryDN;
+ this.modifications = modifications;
+
+ rawEntryDN = new ASN1OctetString(entryDN.toString());
+
+ rawModifications = new ArrayList<RawModification>(modifications.size());
+ for (Modification m : modifications)
+ {
+ rawModifications.add(new LDAPModification(m.getModificationType(),
+ new LDAPAttribute(m.getAttribute())));
+ }
+
+ responseControls = new ArrayList<Control>();
+ cancelRequest = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ByteString getRawEntryDN()
+ {
+ return rawEntryDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawEntryDN(ByteString rawEntryDN)
+ {
+ this.rawEntryDN = rawEntryDN;
+
+ entryDN = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getEntryDN()
+ {
+ if (entryDN == null){
+ try {
+ entryDN = DN.decode(rawEntryDN);
+ }
+ catch (DirectoryException de) {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResultCode(de.getResultCode());
+ appendErrorMessage(de.getErrorMessage());
+ }
+ }
+ return entryDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final List<RawModification> getRawModifications()
+ {
+ return rawModifications;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void addRawModification(RawModification rawModification)
+ {
+ rawModifications.add(rawModification);
+
+ modifications = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawModifications(List<RawModification> rawModifications)
+ {
+ this.rawModifications = rawModifications;
+
+ modifications = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final List<Modification> getModifications()
+ {
+ if (modifications == null)
+ {
+ modifications = new ArrayList<Modification>(rawModifications.size());
+ try {
+ for (RawModification m : rawModifications)
+ {
+ modifications.add(m.toModification());
+ }
+ }
+ catch (LDAPException le)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, le);
+ }
+ setResultCode(ResultCode.valueOf(le.getResultCode()));
+ appendErrorMessage(le.getMessage());
+ modifications = null;
+ }
+ }
+ return modifications;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void addModification(Modification modification)
+ throws DirectoryException
+ {
+ modifications.add(modification);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message,
+ int messageID)
+ {
+ // Before calling clientConnection.disconnect, we need to mark this
+ // operation as cancelled so that the attempt to cancel it later won't cause
+ // an unnecessary delay.
+ setCancelResult(CancelResult.CANCELED);
+
+ clientConnection.disconnect(disconnectReason, sendNotification, message,
+ messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final OperationType getOperationType()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ return OperationType.MODIFY;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String[][] getRequestLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_ENTRY_DN, String.valueOf(rawEntryDN) }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String[][] getResponseLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ String resultCode = String.valueOf(getResultCode().getIntValue());
+
+ String errorMessage;
+ StringBuilder errorMessageBuffer = getErrorMessage();
+ if (errorMessageBuffer == null)
+ {
+ errorMessage = null;
+ }
+ else
+ {
+ errorMessage = errorMessageBuffer.toString();
+ }
+
+ String matchedDNStr;
+ DN matchedDN = getMatchedDN();
+ if (matchedDN == null)
+ {
+ matchedDNStr = null;
+ }
+ else
+ {
+ matchedDNStr = matchedDN.toString();
+ }
+
+ String referrals;
+ List<String> referralURLs = getReferralURLs();
+ if ((referralURLs == null) || referralURLs.isEmpty())
+ {
+ referrals = null;
+ }
+ else
+ {
+ StringBuilder buffer = new StringBuilder();
+ Iterator<String> iterator = referralURLs.iterator();
+ buffer.append(iterator.next());
+
+ while (iterator.hasNext())
+ {
+ buffer.append(", ");
+ buffer.append(iterator.next());
+ }
+
+ referrals = buffer.toString();
+ }
+
+ String processingTime =
+ String.valueOf(getProcessingTime());
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
+ new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
+ new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
+ new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
+ new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return proxiedAuthorizationDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final List<Control> getResponseControls()
+ {
+ return responseControls;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void addResponseControl(Control control)
+ {
+ responseControls.add(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void removeResponseControl(Control control)
+ {
+ responseControls.remove(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final CancelResult cancel(CancelRequest cancelRequest)
+ {
+ this.cancelRequest = cancelRequest;
+
+ CancelResult cancelResult = getCancelResult();
+ long stopWaitingTime = System.currentTimeMillis() + 5000;
+ while ((cancelResult == null) &&
+ (System.currentTimeMillis() < stopWaitingTime))
+ {
+ try
+ {
+ Thread.sleep(50);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+
+ cancelResult = getCancelResult();
+ }
+
+ if (cancelResult == null)
+ {
+ // This can happen in some rare cases (e.g., if a client disconnects and
+ // there is still a lot of data to send to that client), and in this case
+ // we'll prevent the cancel thread from blocking for a long period of
+ // time.
+ cancelResult = CancelResult.CANNOT_CANCEL;
+ }
+
+ return cancelResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final CancelRequest getCancelRequest()
+ {
+ return cancelRequest;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ this.cancelRequest = cancelRequest;
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void toString(StringBuilder buffer)
+ {
+ buffer.append("ModifyOperation(connID=");
+ buffer.append(clientConnection.getConnectionID());
+ buffer.append(", opID=");
+ buffer.append(operationID);
+ buffer.append(", dn=");
+ buffer.append(rawEntryDN);
+ buffer.append(")");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getChangeNumber(){
+ return changeNumber;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setChangeNumber(long changeNumber)
+ {
+ this.changeNumber = changeNumber;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+ {
+ this.proxiedAuthorizationDN = proxiedAuthorizationDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void run()
+ {
+ setResultCode(ResultCode.UNDEFINED);
+
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+ // Start the processing timer.
+ setProcessingStartTime();
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelRequest() != null)
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ return;
+ }
+
+
+ // Create a labeled block of code that we can break out of if a problem is
+ // detected.
+modifyProcessing:
+ {
+ // Invoke the pre-parse modify plugins.
+ PreParsePluginResult preParseResult =
+ pluginConfigManager.invokePreParseModifyPlugins(this);
+ if (preParseResult.connectionTerminated())
+ {
+ // There's no point in continuing with anything. Log the request and
+ // result and return.
+ setResultCode(ResultCode.CANCELED);
+
+ int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
+ appendErrorMessage(getMessage(msgID));
+
+ setProcessingStopTime();
+
+ logModifyRequest(this);
+ logModifyResponse(this);
+ pluginConfigManager.invokePostResponseModifyPlugins(this);
+ return;
+ }
+ else if (preParseResult.sendResponseImmediately())
+ {
+ logModifyRequest(this);
+ break modifyProcessing;
+ }
+ else if (preParseResult.skipCoreProcessing())
+ {
+ break modifyProcessing;
+ }
+
+ // Log the modify request message.
+ logModifyRequest(this);
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelRequest() != null)
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ pluginConfigManager.invokePostResponseModifyPlugins(this);
+ return;
+ }
+
+
+ // Process the entry DN to convert it from the raw form to the form
+ // required for the rest of the modify processing.
+ DN entryDN = getEntryDN();
+ if (entryDN == null){
+ break modifyProcessing;
+ }
+
+
+ // Retrieve the network group attached to the client connection
+ // and get a workflow to process the operation.
+ NetworkGroup ng = getClientConnection().getNetworkGroup();
+ Workflow workflow = ng.getWorkflowCandidate(entryDN);
+ if (workflow == null)
+ {
+ // We have found no workflow for the requested base DN, just return
+ // a no such entry result code and stop the processing.
+ updateOperationErrMsgAndResCode();
+ break modifyProcessing;
+ }
+ workflow.execute(this);
+ }
+
+ // Check for and handle a request to cancel this operation.
+ if ((getCancelRequest() != null) ||
+ (getCancelResult() == CancelResult.CANCELED))
+ {
+ if (getCancelRequest() != null){
+ indicateCancelled(getCancelRequest());
+ }
+ setProcessingStopTime();
+ logModifyResponse(this);
+ invokePostResponsePlugins();
+ return;
+ }
+
+ // Indicate that it is now too late to attempt to cancel the operation.
+ setCancelResult(CancelResult.TOO_LATE);
+
+ // -- DONE AT A LOWER LEVEL --
+ // Notify any change notification listeners that might be registered with
+ // the server.
+
+ // Stop the processing timer.
+ setProcessingStopTime();
+
+ // Send the modify response to the client.
+ getClientConnection().sendResponse(this);
+
+ // Log the modify response.
+ logModifyResponse(this);
+
+ // Check wether there are local operations in attachments
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+ if (localOperations != null && (! localOperations.isEmpty())){
+ for (Object localOp : localOperations)
+ {
+ LocalBackendModifyOperation localOperation =
+ (LocalBackendModifyOperation)localOp;
+ // Notify any persistent searches that might be registered with
+ // the server.
+ if (localOperation.getResultCode() == ResultCode.SUCCESS)
+ {
+ for (PersistentSearch persistentSearch :
+ DirectoryServer.getPersistentSearches())
+ {
+ try
+ {
+ persistentSearch.processModify(localOperation,
+ localOperation.getCurrentEntry(),
+ localOperation.getModifiedEntry());
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ int msgID = MSGID_MODIFY_ERROR_NOTIFYING_PERSISTENT_SEARCH;
+ String message = getMessage(msgID,
+ String.valueOf(persistentSearch),
+ getExceptionMessage(e));
+ logError(ErrorLogCategory.CORE_SERVER,
+ ErrorLogSeverity.SEVERE_ERROR,
+ message, msgID);
+
+ DirectoryServer.deregisterPersistentSearch(persistentSearch);
+ }
+ }
+ }
+
+ // Invoke the post-response modify plugins.
+ pluginConfigManager.invokePostResponseModifyPlugins(localOperation);
+ }
+ }
+ }
+
+ /**
+ * Updates the error message and the result code of the operation.
+ *
+ * This method is called because no workflows were found to process
+ * the operation.
+ */
+ private void updateOperationErrMsgAndResCode()
+ {
+ setResultCode(ResultCode.NO_SUCH_OBJECT);
+ appendErrorMessage(getMessage(MSGID_MODIFY_NO_SUCH_ENTRY,
+ String.valueOf(getEntryDN())));
+ }
+
+ /**
+ * Execute the postResponseModifyPlugins.
+ */
+ private void invokePostResponsePlugins()
+ {
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+ // Check wether there are local operations in attachments
+ List localOperations =
+ (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
+
+ if (localOperations != null && (! localOperations.isEmpty())){
+ for (Object localOp : localOperations)
+ {
+ LocalBackendModifyOperation localOperation =
+ (LocalBackendModifyOperation)localOp;
+ // Invoke the post-response add plugins.
+ pluginConfigManager.invokePostResponseModifyPlugins(localOperation);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This method always returns null.
+ */
+ public Entry getCurrentEntry() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This method always returns null.
+ */
+ public List<AttributeValue> getCurrentPasswords()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This method always returns null.
+ */
+ public Entry getModifiedEntry()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This method always returns null.
+ */
+ public List<AttributeValue> getNewPasswords()
+ {
+ return null;
+ }
+
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperationWrapper.java b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperationWrapper.java
new file mode 100644
index 0000000..46968f3
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/ModifyOperationWrapper.java
@@ -0,0 +1,622 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.Modification;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.RawModification;
+import org.opends.server.types.ResultCode;
+
+/**
+ * This abstract class wraps/decorates a given modify operation.
+ * This class will be extended by sub-classes to enhance the
+ * functionnality of the ModifyOperationBasis.
+ */
+public abstract class ModifyOperationWrapper implements ModifyOperation
+{
+ private ModifyOperation modify;
+
+ /**
+ * Creates a new modify operation based on the provided modify operation.
+ *
+ * @param modify The modify operation to wrap
+ */
+ protected ModifyOperationWrapper(ModifyOperation modify){
+ this.modify = modify;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addModification(Modification modification)
+ throws DirectoryException
+ {
+ modify.addModification(modification);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addRawModification(RawModification rawModification)
+ {
+ modify.addRawModification(rawModification);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addResponseControl(Control control)
+ {
+ modify.addResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult cancel(CancelRequest cancelRequest)
+ {
+ return modify.cancel(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message, int messageID)
+ {
+ modify.disconnectClient(disconnectReason, sendNotification,
+ message, messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean dontSynchronize()
+ {
+ return modify.dontSynchronize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj)
+ {
+ return modify.equals(obj);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelRequest getCancelRequest()
+ {
+ return modify.getCancelRequest();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getEntryDN()
+ {
+ return modify.getEntryDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Modification> getModifications()
+ {
+ return modify.getModifications();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public OperationType getOperationType()
+ {
+ return modify.getOperationType();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStartTime()
+ {
+ return modify.getProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStopTime()
+ {
+ return modify.getProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingTime()
+ {
+ return modify.getProcessingTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString getRawEntryDN()
+ {
+ return modify.getRawEntryDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<RawModification> getRawModifications()
+ {
+ return modify.getRawModifications();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getRequestLogElements()
+ {
+ return modify.getRequestLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getResponseControls()
+ {
+ return modify.getResponseControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getResponseLogElements()
+ {
+ return modify.getResponseLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode()
+ {
+ return modify.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeResponseControl(Control control)
+ {
+ modify.removeResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean setCancelRequest(CancelRequest cancelRequest){
+ return modify.setCancelRequest(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawEntryDN(ByteString rawEntryDN)
+ {
+ modify.setRawEntryDN(rawEntryDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawModifications(List<RawModification> rawModifications)
+ {
+ modify.setRawModifications(rawModifications);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void toString(StringBuilder buffer)
+ {
+ modify.toString(buffer);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStopTime(){
+ modify.setProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStartTime(){
+ modify.setProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addRequestControl(Control control)
+ {
+ modify.addRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendAdditionalLogMessage(String message)
+ {
+ modify.appendAdditionalLogMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendErrorMessage(String message)
+ {
+ modify.appendErrorMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getAdditionalLogMessage()
+ {
+ return modify.getAdditionalLogMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getAttachment(String name)
+ {
+ return modify.getAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<String, Object> getAttachments()
+ {
+ return modify.getAttachments();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getAuthorizationDN()
+ {
+ return modify.getAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry getAuthorizationEntry()
+ {
+ return modify.getAuthorizationEntry();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult getCancelResult()
+ {
+ return modify.getCancelResult();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClientConnection getClientConnection()
+ {
+ return modify.getClientConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getCommonLogElements()
+ {
+ return modify.getCommonLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getConnectionID()
+ {
+ return modify.getConnectionID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getErrorMessage()
+ {
+ return modify.getErrorMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getMatchedDN()
+ {
+ return modify.getMatchedDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMessageID()
+ {
+ return modify.getMessageID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getOperationID()
+ {
+ return modify.getOperationID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<String> getReferralURLs()
+ {
+ return modify.getReferralURLs();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getRequestControls()
+ {
+ return modify.getRequestControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultCode getResultCode()
+ {
+ return modify.getResultCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void indicateCancelled(CancelRequest cancelRequest)
+ {
+ modify.indicateCancelled(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isInternalOperation()
+ {
+ return modify.isInternalOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSynchronizationOperation()
+ {
+ return modify.isSynchronizationOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void operationCompleted()
+ {
+ modify.operationCompleted();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object removeAttachment(String name)
+ {
+ return modify.removeAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeRequestControl(Control control)
+ {
+ modify.removeRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAdditionalLogMessage(StringBuilder additionalLogMessage)
+ {
+ modify.setAdditionalLogMessage(additionalLogMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object setAttachment(String name, Object value)
+ {
+ return modify.setAttachment(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttachments(Map<String, Object> attachments)
+ {
+ modify.setAttachments(attachments);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAuthorizationEntry(Entry authorizationEntry)
+ {
+ modify.setAuthorizationEntry(authorizationEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCancelResult(CancelResult cancelResult)
+ {
+ modify.setCancelResult(cancelResult);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDontSynchronize(boolean dontSynchronize)
+ {
+ modify.setDontSynchronize(dontSynchronize);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setErrorMessage(StringBuilder errorMessage)
+ {
+ modify.setErrorMessage(errorMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInternalOperation(boolean isInternalOperation)
+ {
+ modify.setInternalOperation(isInternalOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMatchedDN(DN matchedDN)
+ {
+ modify.setMatchedDN(matchedDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setReferralURLs(List<String> referralURLs)
+ {
+ modify.setReferralURLs(referralURLs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResponseData(DirectoryException directoryException)
+ {
+ modify.setResponseData(directoryException);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResultCode(ResultCode resultCode)
+ {
+ modify.setResultCode(resultCode);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSynchronizationOperation(boolean isSynchronizationOperation)
+ {
+ modify.setSynchronizationOperation(isSynchronizationOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return modify.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getChangeNumber(){
+ return modify.getChangeNumber();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setChangeNumber(long changeNumber)
+ {
+ modify.setChangeNumber(changeNumber);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return modify.getProxiedAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN){
+ modify.setProxiedAuthorizationDN(proxiedAuthorizationDN);
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroup.java b/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroup.java
new file mode 100644
index 0000000..516e24d
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroup.java
@@ -0,0 +1,407 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import java.util.ArrayList;
+
+import org.opends.server.types.DN;
+import org.opends.server.workflowelement.WorkflowElement;
+
+
+/**
+ * This class defines the network group. A network group is used to categorize
+ * client connections. A network group is defined by a set of criteria, a
+ * set of policies and a set of workflows. A client connection belongs to a
+ * network group whenever it satisfies all the network group criteria. As soon
+ * as a client connection belongs to a network group, it has to comply with
+ * all the network group policies and all the client operation can be routed
+ * to one the network group workflows.
+ */
+public class NetworkGroup
+{
+ // Workflows registered with the current network group.
+ private ArrayList<WorkflowTopologyNode> registeredWorkflows =
+ new ArrayList<WorkflowTopologyNode>();
+
+
+ // The workflow for the rootDSE entry. The RootDSE workflow
+ // is not stored in the list of registered workflows.
+ private RootDseWorkflowTopology rootDSEWorkflow = null;
+
+
+ // List of naming contexts handled by the network group.
+ private NetworkGroupNamingContexts namingContexts =
+ new NetworkGroupNamingContexts();
+
+
+ // The default network group (singleton).
+ // The default network group has no criterion, no policy, and gives
+ // access to all the workflows. The purpose of the default network
+ // group is to allow new clients to perform a first operation before
+ // they can be attached to a specific network group.
+ private static NetworkGroup defaultNetworkGroup =
+ new NetworkGroup ("default");
+
+
+ // The list of all network groups that have been created.
+ // The default network group is not stored in that pool.
+ private static ArrayList<NetworkGroup> networkGroupPool =
+ new ArrayList<NetworkGroup>();
+
+
+ // Human readable network group name.
+ private String networkGroupName = null;
+
+
+ /**
+ * Creates a new instance of the network group.
+ *
+ * @param networkGroupName the name of the network group for debug purpose
+ */
+ public NetworkGroup (
+ String networkGroupName
+ )
+ {
+ this.networkGroupName = networkGroupName;
+ }
+
+
+ /**
+ * Registers a network group with the pool of network groups.
+ *
+ * @param networkGroup the network group to register
+ */
+ public static void registerNetworkGroup(
+ NetworkGroup networkGroup
+ )
+ {
+ networkGroupPool.add(networkGroup);
+ }
+
+
+ /**
+ * Registers a workflow with the network group.
+ *
+ * @param workflow the workflow to register
+ */
+ public void registerWorkflow(
+ WorkflowImpl workflow
+ )
+ {
+ // The workflow is rgistered with no pre/post workflow element.
+ registerWorkflow(workflow, null, null);
+ }
+
+
+ /**
+ * Registers a workflow with the network group and the workflow may have
+ * pre and post workflow element.
+ *
+ * @param workflow the workflow to register
+ * @param preWorkflowElements the tasks to execute before the workflow
+ * @param postWorkflowElements the tasks to execute after the workflow
+ */
+ private void registerWorkflow(
+ WorkflowImpl workflow,
+ WorkflowElement[] preWorkflowElements,
+ WorkflowElement[] postWorkflowElements
+ )
+ {
+ // true as soon as the workflow has been registered
+ boolean registered = false;
+
+ // Is it the rootDSE workflow?
+ DN baseDN = workflow.getBaseDN();
+ if (baseDN.isNullDN())
+ {
+ // NOTE - The rootDSE workflow is not stored in the pool.
+ rootDSEWorkflow = new RootDseWorkflowTopology(workflow, namingContexts);
+ registered = true;
+ }
+ else
+ {
+ // This workflow is not the rootDSE workflow. Try to insert it in the
+ // workflow topology.
+ if (! baseDNAlreadyRegistered(baseDN))
+ {
+ WorkflowTopologyNode workflowTopology = new WorkflowTopologyNode(
+ workflow, preWorkflowElements, postWorkflowElements);
+
+ // Add the workflow in the workflow topology...
+ for (WorkflowTopologyNode curWorkflow: registeredWorkflows)
+ {
+ // Try to insert the new workflow under an existing workflow...
+ if (curWorkflow.insertSubordinate(workflowTopology))
+ {
+ // new workflow has been inserted in the topology
+ break;
+ }
+
+ // ... or try to insert the existing workflow below the new
+ // workflow
+ if (workflowTopology.insertSubordinate(curWorkflow))
+ {
+ // new workflow has been inserted in the topology
+ break;
+ }
+ }
+
+ // ... then register the workflow with the pool.
+ registeredWorkflows.add(workflowTopology);
+ registered = true;
+
+ // Rebuild the list of naming context handled by the network group
+ rebuildNamingContextList();
+ }
+ }
+
+ // If the workflow has been registered successfully then register it
+ // with the default network group
+ if (registered)
+ {
+ if (this != defaultNetworkGroup)
+ {
+ defaultNetworkGroup.registerWorkflow(
+ workflow, preWorkflowElements, postWorkflowElements);
+ }
+ }
+ }
+
+
+ /**
+ * Deregisters a workflow with the network group.
+ *
+ * @param baseDN the baseDN of the workflow to deregister
+ */
+ public void deregisterWorkflow (
+ DN baseDN
+ )
+ {
+ Workflow workflow = getWorkflowCandidate(baseDN);
+ if (workflow != null)
+ {
+ deregisterWorkflow(workflow);
+ }
+ }
+
+
+ /**
+ * Deregisters a workflow with the network group.
+ *
+ * @param workflow the workflow to deregister
+ */
+ private void deregisterWorkflow(
+ Workflow workflow
+ )
+ {
+ // true as soon as the workflow has been deregistered
+ boolean deregistered = false;
+
+ // Is it the rootDSE workflow?
+ if (workflow == rootDSEWorkflow)
+ {
+ rootDSEWorkflow = null;
+ deregistered = true;
+ }
+ else
+ {
+ // The workflow to deregister is not the root DSE workflow.
+ // Remove it from the workflow topology.
+ WorkflowTopologyNode workflowTopology = (WorkflowTopologyNode) workflow;
+ workflowTopology.remove();
+
+ // Then deregister the workflow with the network group.
+ registeredWorkflows.remove(workflow);
+ deregistered = true;
+
+ // Rebuild the list of naming context handled by the network group
+ rebuildNamingContextList();
+ }
+
+ // If the workflow has been deregistered then deregister it with
+ // the default network group as well
+ if (deregistered)
+ {
+ if (this != defaultNetworkGroup)
+ {
+ defaultNetworkGroup.deregisterWorkflow(workflow);
+ }
+ }
+ }
+
+
+ /**
+ * Gets the highest workflow in the topology that can handle the baseDN.
+ *
+ * @param baseDN the base DN of the request
+ * @return the highest workflow in the topology that can handle the base DN,
+ * <code>null</code> if none was found
+ */
+ public Workflow getWorkflowCandidate (
+ DN baseDN
+ )
+ {
+ // the top workflow to return
+ Workflow workflowCandidate = null;
+
+ // get the list of workflow candidates
+ if (baseDN.isNullDN())
+ {
+ // The rootDSE workflow is the candidate.
+ workflowCandidate = rootDSEWorkflow;
+ }
+ else
+ {
+ // Search the highest workflow in the topology that can handle
+ // the baseDN.
+ for (WorkflowTopologyNode curWorkflow: namingContexts.getNamingContexts())
+ {
+ workflowCandidate = curWorkflow.getWorkflowCandidate (baseDN);
+ if (workflowCandidate != null)
+ {
+ break;
+ }
+ }
+ }
+
+ return workflowCandidate;
+ }
+
+
+ /**
+ * Returns the default network group. The default network group is always
+ * defined and has no criterion, no policy and provide full access to
+ * all the registered workflows.
+ *
+ * @return the default network group
+ */
+ public static NetworkGroup getDefaultNetworkGroup()
+ {
+ return defaultNetworkGroup;
+ }
+
+
+ /**
+ * Rebuilds the list of naming contexts handled by the network group.
+ * This operation should be performed whenever a workflow topology
+ * has been updated (workflow registration or de-registration).
+ */
+ private void rebuildNamingContextList()
+ {
+ // reset lists of naming contexts
+ namingContexts.resetLists();
+
+ // a registered workflow with no parent is a naming context
+ for (WorkflowTopologyNode curWorkflow: registeredWorkflows)
+ {
+ WorkflowTopologyNode parent = curWorkflow.getParent();
+ if (parent == null)
+ {
+ namingContexts.addNamingContext (curWorkflow);
+ }
+ }
+ }
+
+
+ /**
+ * Checks whether a base DN has been already registered with
+ * the network group.
+ *
+ * @param baseDN the base DN to check
+ * @return <code>false</code> if the base DN is registered with the
+ * network group, <code>false</code> otherwise
+ */
+ private boolean baseDNAlreadyRegistered (
+ DN baseDN
+ )
+ {
+ // returned result
+ boolean alreadyRegistered = false;
+
+ // go through the list of registered workflow and check whether a base DN
+ // has already been used in a registered workflow
+ for (WorkflowTopologyNode curWorkflow: registeredWorkflows)
+ {
+ DN curDN = curWorkflow.getBaseDN();
+ if (baseDN.equals (curDN))
+ {
+ alreadyRegistered = true;
+ break;
+ }
+ }
+
+ // check done
+ return alreadyRegistered;
+ }
+
+
+ /**
+ * Returns the list of naming contexts handled by the network group.
+ *
+ * @return the list of naming contexts
+ */
+ public NetworkGroupNamingContexts getNamingContexts()
+ {
+ return namingContexts;
+ }
+
+
+ /**
+ * Dumps info from the current network group for debug purpose.
+ *
+ * @param leftMargin white spaces used to indent traces
+ * @return a string buffer that contains trace information
+ */
+ public StringBuffer toString (String leftMargin)
+ {
+ StringBuffer sb = new StringBuffer();
+ String newMargin = leftMargin + " ";
+
+ sb.append (leftMargin + "Networkgroup (" + networkGroupName+ "\n");
+ sb.append (leftMargin + "List of registered workflows:\n");
+ for (WorkflowTopologyNode w: registeredWorkflows)
+ {
+ sb.append (w.toString (newMargin));
+ }
+
+ namingContexts.toString (leftMargin);
+
+ sb.append (leftMargin + "rootDSEWorkflow:\n");
+ if (rootDSEWorkflow == null)
+ {
+ sb.append (newMargin + "null\n");
+ }
+ else
+ {
+ sb.append (rootDSEWorkflow.toString (newMargin));
+ }
+
+ return sb;
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupCriteria.java b/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupCriteria.java
new file mode 100644
index 0000000..8f9b9ba
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupCriteria.java
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+/**
+ * This class defines the network group criteria. A criterion is used
+ * by the network groups to determine whether a client connection belongs
+ * to the network group or not.
+ */
+public class NetworkGroupCriteria
+{
+
+ /**
+ * Creates a new instance of the network group criteria.
+ */
+ public NetworkGroupCriteria()
+ {
+ // No implementation is required.
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupNamingContexts.java b/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupNamingContexts.java
new file mode 100644
index 0000000..f71df58
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupNamingContexts.java
@@ -0,0 +1,157 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import java.util.ArrayList;
+
+
+/**
+ * This classes defines a list of naming contexts for a network group.
+ */
+public class NetworkGroupNamingContexts
+{
+ // List of naming contexts.
+ private ArrayList<WorkflowTopologyNode> namingContexts = null;
+
+ // List of public naming contexts.
+ private ArrayList<WorkflowTopologyNode> publicNamingContexts = null;
+
+ // List of private naming contexts.
+ private ArrayList<WorkflowTopologyNode> privateNamingContexts = null;
+
+ /**
+ * Create a list of naming contexts for a network group.
+ */
+ public NetworkGroupNamingContexts()
+ {
+ // create the lists of naming contexts
+ resetLists();
+ }
+
+
+ /**
+ * Reset the list of naming contexts.
+ */
+ public void resetLists()
+ {
+ namingContexts = new ArrayList<WorkflowTopologyNode>();
+ privateNamingContexts = new ArrayList<WorkflowTopologyNode>();
+ publicNamingContexts = new ArrayList<WorkflowTopologyNode>();
+ }
+
+
+ /**
+ * Add a workflow in the list of naming context.
+ *
+ * @param workflow the workflow to add in the list of naming contexts
+ */
+ public void addNamingContext (
+ WorkflowTopologyNode workflow
+ )
+ {
+ // add the workflow to the list of naming context
+ namingContexts.add (workflow);
+
+ // add the workflow to the private/public list of naming contexts
+ if (workflow.isPrivate())
+ {
+ privateNamingContexts.add (workflow);
+ }
+ else
+ {
+ publicNamingContexts.add (workflow);
+ }
+ }
+
+
+ /**
+ * Get the list of naming contexts.
+ *
+ * @return the list of all the naming contexts
+ */
+ public ArrayList<WorkflowTopologyNode> getNamingContexts()
+ {
+ return namingContexts;
+ }
+
+
+ /**
+ * Get the list of private naming contexts.
+ *
+ * @return the list of private naming contexts
+ */
+ public ArrayList<WorkflowTopologyNode> getPrivateNamingContexts()
+ {
+ return privateNamingContexts;
+ }
+
+
+ /**
+ * Get the list of public naming contexts.
+ *
+ * @return the list of public naming contexts
+ */
+ public ArrayList<WorkflowTopologyNode> getPublicNamingContexts()
+ {
+ return publicNamingContexts;
+ }
+
+
+ /**
+ * Dumps info from the current networkk group for debug purpose.
+ *
+ * @param leftMargin white spaces used to indent traces
+ * @return a string buffer that contains trace information
+ */
+ public StringBuffer toString (String leftMargin)
+ {
+ StringBuffer sb = new StringBuffer();
+ String newMargin = leftMargin + " ";
+
+ sb.append (leftMargin + "List of naming contexts:\n");
+ for (WorkflowTopologyNode w: namingContexts)
+ {
+ sb.append (w.toString (newMargin));
+ }
+
+ sb.append (leftMargin + "List of PRIVATE naming contexts:\n");
+ for (WorkflowTopologyNode w: privateNamingContexts)
+ {
+ sb.append (w.toString (newMargin));
+ }
+
+ sb.append (leftMargin + "List of PUBLIC naming contexts:\n");
+ for (WorkflowTopologyNode w: publicNamingContexts)
+ {
+ sb.append (w.toString (newMargin));
+ }
+
+ return sb;
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupPolicy.java b/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupPolicy.java
new file mode 100644
index 0000000..f29eb29
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/NetworkGroupPolicy.java
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+/**
+ * This class defines the network group policy. A client connection
+ * that belongs to a network group has to comply with the policies
+ * attach to the network group.
+ */
+public class NetworkGroupPolicy
+{
+
+ /**
+ * Creates a new instance of the network group policy.
+ */
+ public NetworkGroupPolicy()
+ {
+ // No implementation is required.
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/PersistentSearch.java b/opendj-sdk/opends/src/server/org/opends/server/core/PersistentSearch.java
index 855f691..0a20345 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/PersistentSearch.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/PersistentSearch.java
@@ -27,19 +27,19 @@
package org.opends.server.core;
-
import java.util.ArrayList;
import java.util.Set;
import org.opends.server.controls.EntryChangeNotificationControl;
import org.opends.server.controls.PersistentSearchChangeType;
import org.opends.server.types.Control;
+import org.opends.server.types.DN;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchScope;
+import org.opends.server.workflowelement.localbackend.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
@@ -181,7 +181,7 @@
* @param addOperation The add operation that has been processed.
* @param entry The entry that was added.
*/
- public void processAdd(AddOperation addOperation, Entry entry)
+ public void processAdd(LocalBackendAddOperation addOperation, Entry entry)
{
// See if we care about add operations.
if (! changeTypes.contains(PersistentSearchChangeType.ADD))
@@ -296,7 +296,8 @@
* @param deleteOperation The delete operation that has been processed.
* @param entry The entry that was removed.
*/
- public void processDelete(DeleteOperation deleteOperation, Entry entry)
+ public void processDelete(LocalBackendDeleteOperation deleteOperation,
+ Entry entry)
{
// See if we care about delete operations.
if (! changeTypes.contains(PersistentSearchChangeType.DELETE))
@@ -412,7 +413,8 @@
* @param oldEntry The entry before the modification was applied.
* @param newEntry The entry after the modification was applied.
*/
- public void processModify(ModifyOperation modifyOperation, Entry oldEntry,
+ public void processModify(LocalBackendModifyOperation modifyOperation,
+ Entry oldEntry,
Entry newEntry)
{
// See if we care about modify operations.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/PluginConfigManager.java b/opendj-sdk/opends/src/server/org/opends/server/core/PluginConfigManager.java
index ae23fab..a5a75a2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/PluginConfigManager.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/PluginConfigManager.java
@@ -80,6 +80,28 @@
import org.opends.server.types.SearchResultReference;
import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.operation.PostOperationAddOperation;
+import org.opends.server.types.operation.PostOperationBindOperation;
+import org.opends.server.types.operation.PostOperationDeleteOperation;
+import org.opends.server.types.operation.PostOperationModifyOperation;
+import org.opends.server.types.operation.PostOperationSearchOperation;
+import org.opends.server.types.operation.PostResponseAddOperation;
+import org.opends.server.types.operation.PostResponseBindOperation;
+import org.opends.server.types.operation.PostResponseDeleteOperation;
+import org.opends.server.types.operation.PostResponseModifyOperation;
+import org.opends.server.types.operation.PostResponseSearchOperation;
+import org.opends.server.types.operation.PreOperationAddOperation;
+import org.opends.server.types.operation.PreOperationBindOperation;
+import org.opends.server.types.operation.PreOperationDeleteOperation;
+import org.opends.server.types.operation.PreOperationModifyOperation;
+import org.opends.server.types.operation.PreOperationSearchOperation;
+import org.opends.server.types.operation.PreParseAddOperation;
+import org.opends.server.types.operation.PreParseBindOperation;
+import org.opends.server.types.operation.PreParseDeleteOperation;
+import org.opends.server.types.operation.PreParseModifyOperation;
+import org.opends.server.types.operation.PreParseSearchOperation;
+import org.opends.server.workflowelement.localbackend.*;
+
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
@@ -1758,8 +1780,8 @@
*
* @return The result of processing the pre-parse add plugins.
*/
- public PreParsePluginResult invokePreParseAddPlugins(AddOperation
- addOperation)
+ public PreParsePluginResult invokePreParseAddPlugins(
+ PreParseAddOperation addOperation)
{
PreParsePluginResult result = null;
@@ -1839,7 +1861,7 @@
* @return The result of processing the pre-parse bind plugins.
*/
public PreParsePluginResult invokePreParseBindPlugins(
- BindOperation bindOperation)
+ PreParseBindOperation bindOperation)
{
PreParsePluginResult result = null;
@@ -2001,7 +2023,7 @@
* @return The result of processing the pre-parse delete plugins.
*/
public PreParsePluginResult invokePreParseDeletePlugins(
- DeleteOperation deleteOperation)
+ PreParseDeleteOperation deleteOperation)
{
PreParsePluginResult result = null;
@@ -2159,13 +2181,13 @@
* Invokes the set of pre-parse modify plugins that have been configured in
* the Directory Server.
*
- * @param modifyOperation The modify operation for which to invoke the
+ * @param operation The modify operation for which to invoke the
* pre-parse plugins.
*
* @return The result of processing the pre-parse modify plugins.
*/
public PreParsePluginResult invokePreParseModifyPlugins(
- ModifyOperation modifyOperation)
+ PreParseModifyOperation operation)
{
PreParsePluginResult result = null;
@@ -2173,7 +2195,7 @@
{
try
{
- result = p.doPreParse(modifyOperation);
+ result = p.doPreParse(operation);
}
catch (Exception e)
{
@@ -2185,17 +2207,17 @@
int msgID = MSGID_PLUGIN_PRE_PARSE_PLUGIN_EXCEPTION;
String message =
getMessage(msgID,
- modifyOperation.getOperationType().getOperationName(),
+ operation.getOperationType().getOperationName(),
String.valueOf(p.getPluginEntryDN()),
- modifyOperation.getConnectionID(),
- modifyOperation.getOperationID(),
+ operation.getConnectionID(),
+ operation.getOperationID(),
stackTraceToSingleLineString(e));
logError(ErrorLogCategory.PLUGIN, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- modifyOperation.setResultCode(
+ operation.setResultCode(
DirectoryServer.getServerErrorResultCode());
- modifyOperation.appendErrorMessage(message);
+ operation.appendErrorMessage(message);
return new PreParsePluginResult(false, false, true);
}
@@ -2205,16 +2227,16 @@
int msgID = MSGID_PLUGIN_PRE_PARSE_PLUGIN_RETURNED_NULL;
String message =
getMessage(msgID,
- modifyOperation.getOperationType().getOperationName(),
+ operation.getOperationType().getOperationName(),
String.valueOf(p.getPluginEntryDN()),
- modifyOperation.getConnectionID(),
- modifyOperation.getOperationID());
+ operation.getConnectionID(),
+ operation.getOperationID());
logError(ErrorLogCategory.PLUGIN, ErrorLogSeverity.SEVERE_ERROR,
message, msgID);
- modifyOperation.setResultCode(
+ operation.setResultCode(
DirectoryServer.getServerErrorResultCode());
- modifyOperation.appendErrorMessage(message);
+ operation.appendErrorMessage(message);
return new PreParsePluginResult(false, false, true);
}
@@ -2329,7 +2351,7 @@
* @return The result of processing the pre-parse search plugins.
*/
public PreParsePluginResult invokePreParseSearchPlugins(
- SearchOperation searchOperation)
+ PreParseSearchOperation searchOperation)
{
PreParsePluginResult result = null;
@@ -2493,7 +2515,7 @@
* @return The result of processing the pre-operation add plugins.
*/
public PreOperationPluginResult invokePreOperationAddPlugins(
- AddOperation addOperation)
+ PreOperationAddOperation addOperation)
{
PreOperationPluginResult result = null;
@@ -2573,7 +2595,7 @@
* @return The result of processing the pre-operation bind plugins.
*/
public PreOperationPluginResult invokePreOperationBindPlugins(
- BindOperation bindOperation)
+ PreOperationBindOperation bindOperation)
{
PreOperationPluginResult result = null;
@@ -2735,7 +2757,7 @@
* @return The result of processing the pre-operation delete plugins.
*/
public PreOperationPluginResult invokePreOperationDeletePlugins(
- DeleteOperation deleteOperation)
+ PreOperationDeleteOperation deleteOperation)
{
PreOperationPluginResult result = null;
@@ -2899,7 +2921,7 @@
* @return The result of processing the pre-operation modify plugins.
*/
public PreOperationPluginResult invokePreOperationModifyPlugins(
- ModifyOperation modifyOperation)
+ PreOperationModifyOperation modifyOperation)
{
PreOperationPluginResult result = null;
@@ -3063,7 +3085,7 @@
* @return The result of processing the pre-operation search plugins.
*/
public PreOperationPluginResult invokePreOperationSearchPlugins(
- SearchOperation searchOperation)
+ PreOperationSearchOperation searchOperation)
{
PreOperationPluginResult result = null;
@@ -3227,7 +3249,7 @@
* @return The result of processing the post-operation add plugins.
*/
public PostOperationPluginResult invokePostOperationAddPlugins(
- AddOperation addOperation)
+ PostOperationAddOperation addOperation)
{
PostOperationPluginResult result = null;
@@ -3307,7 +3329,7 @@
* @return The result of processing the post-operation bind plugins.
*/
public PostOperationPluginResult invokePostOperationBindPlugins(
- BindOperation bindOperation)
+ PostOperationBindOperation bindOperation)
{
PostOperationPluginResult result = null;
@@ -3469,7 +3491,7 @@
* @return The result of processing the post-operation delete plugins.
*/
public PostOperationPluginResult invokePostOperationDeletePlugins(
- DeleteOperation deleteOperation)
+ PostOperationDeleteOperation deleteOperation)
{
PostOperationPluginResult result = null;
@@ -3633,7 +3655,7 @@
* @return The result of processing the post-operation modify plugins.
*/
public PostOperationPluginResult invokePostOperationModifyPlugins(
- ModifyOperation modifyOperation)
+ PostOperationModifyOperation modifyOperation)
{
PostOperationPluginResult result = null;
@@ -3797,7 +3819,7 @@
* @return The result of processing the post-operation search plugins.
*/
public PostOperationPluginResult invokePostOperationSearchPlugins(
- SearchOperation searchOperation)
+ PostOperationSearchOperation searchOperation)
{
PostOperationPluginResult result = null;
@@ -3961,7 +3983,7 @@
* @return The result of processing the post-response add plugins.
*/
public PostResponsePluginResult invokePostResponseAddPlugins(
- AddOperation addOperation)
+ PostResponseAddOperation addOperation)
{
PostResponsePluginResult result = null;
@@ -4035,7 +4057,7 @@
* @return The result of processing the post-response bind plugins.
*/
public PostResponsePluginResult invokePostResponseBindPlugins(
- BindOperation bindOperation)
+ PostResponseBindOperation bindOperation)
{
PostResponsePluginResult result = null;
@@ -4183,7 +4205,7 @@
* @return The result of processing the post-response delete plugins.
*/
public PostResponsePluginResult invokePostResponseDeletePlugins(
- DeleteOperation deleteOperation)
+ PostResponseDeleteOperation deleteOperation)
{
PostResponsePluginResult result = null;
@@ -4331,7 +4353,7 @@
* @return The result of processing the post-response modify plugins.
*/
public PostResponsePluginResult invokePostResponseModifyPlugins(
- ModifyOperation modifyOperation)
+ PostResponseModifyOperation modifyOperation)
{
PostResponsePluginResult result = null;
@@ -4479,7 +4501,7 @@
* @return The result of processing the post-response search plugins.
*/
public PostResponsePluginResult invokePostResponseSearchPlugins(
- SearchOperation searchOperation)
+ PostResponseSearchOperation searchOperation)
{
PostResponsePluginResult result = null;
@@ -4541,7 +4563,75 @@
return result;
}
+ /**
+ * Invokes the set of search result entry plugins that have been configured
+ * in the Directory Server.
+ *
+ * @param searchOperation The search operation for which to invoke the
+ * search result entry plugins.
+ * @param searchEntry The search result entry to be processed.
+ *
+ * @return The result of processing the search result entry plugins.
+ */
+ public SearchEntryPluginResult invokeSearchResultEntryPlugins(
+ LocalBackendSearchOperation searchOperation,
+ SearchResultEntry searchEntry)
+ {
+ SearchEntryPluginResult result = null;
+ for (DirectoryServerPlugin p : searchResultEntryPlugins)
+ {
+ try
+ {
+ result = p.processSearchEntry(searchOperation, searchEntry);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ int msgID = MSGID_PLUGIN_SEARCH_ENTRY_PLUGIN_EXCEPTION;
+ String message = getMessage(msgID, String.valueOf(p.getPluginEntryDN()),
+ searchOperation.getConnectionID(),
+ searchOperation.getOperationID(),
+ String.valueOf(searchEntry.getDN()),
+ stackTraceToSingleLineString(e));
+ logError(ErrorLogCategory.PLUGIN, ErrorLogSeverity.SEVERE_ERROR,
+ message, msgID);
+
+ return new SearchEntryPluginResult(false, false, false, false);
+ }
+
+ if (result == null)
+ {
+ int msgID = MSGID_PLUGIN_SEARCH_ENTRY_PLUGIN_RETURNED_NULL;
+ String message = getMessage(msgID, String.valueOf(p.getPluginEntryDN()),
+ searchOperation.getConnectionID(),
+ searchOperation.getOperationID(),
+ String.valueOf(searchEntry.getDN()));
+ logError(ErrorLogCategory.PLUGIN, ErrorLogSeverity.SEVERE_ERROR,
+ message, msgID);
+
+ return new SearchEntryPluginResult(false, false, false, false);
+ }
+ else if (result.connectionTerminated() ||
+ (! result.continuePluginProcessing()))
+ {
+ return result;
+ }
+ }
+
+ if (result == null)
+ {
+ // This should only happen if there were no search result entry plugins
+ // registered, which is fine.
+ result = SearchEntryPluginResult.SUCCESS;
+ }
+
+ return result;
+ }
/**
* Invokes the set of search result entry plugins that have been configured
@@ -4554,7 +4644,7 @@
* @return The result of processing the search result entry plugins.
*/
public SearchEntryPluginResult invokeSearchResultEntryPlugins(
- SearchOperation searchOperation,
+ SearchOperationBasis searchOperation,
SearchResultEntry searchEntry)
{
SearchEntryPluginResult result = null;
@@ -4613,7 +4703,75 @@
return result;
}
+ /**
+ * Invokes the set of search result reference plugins that have been
+ * configured in the Directory Server.
+ *
+ * @param searchOperation The search operation for which to invoke the
+ * search result reference plugins.
+ * @param searchReference The search result reference to be processed.
+ *
+ * @return The result of processing the search result reference plugins.
+ */
+ public SearchReferencePluginResult invokeSearchResultReferencePlugins(
+ LocalBackendSearchOperation searchOperation,
+ SearchResultReference searchReference)
+ {
+ SearchReferencePluginResult result = null;
+ for (DirectoryServerPlugin p : searchResultReferencePlugins)
+ {
+ try
+ {
+ result = p.processSearchReference(searchOperation, searchReference);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ int msgID = MSGID_PLUGIN_SEARCH_REFERENCE_PLUGIN_EXCEPTION;
+ String message = getMessage(msgID, String.valueOf(p.getPluginEntryDN()),
+ searchOperation.getConnectionID(),
+ searchOperation.getOperationID(),
+ searchReference.getReferralURLString(),
+ stackTraceToSingleLineString(e));
+ logError(ErrorLogCategory.PLUGIN, ErrorLogSeverity.SEVERE_ERROR,
+ message, msgID);
+
+ return new SearchReferencePluginResult(false, false, false, false);
+ }
+
+ if (result == null)
+ {
+ int msgID = MSGID_PLUGIN_SEARCH_REFERENCE_PLUGIN_RETURNED_NULL;
+ String message = getMessage(msgID, String.valueOf(p.getPluginEntryDN()),
+ searchOperation.getConnectionID(),
+ searchOperation.getOperationID(),
+ searchReference.getReferralURLString());
+ logError(ErrorLogCategory.PLUGIN, ErrorLogSeverity.SEVERE_ERROR,
+ message, msgID);
+
+ return new SearchReferencePluginResult(false, false, false, false);
+ }
+ else if (result.connectionTerminated() ||
+ (! result.continuePluginProcessing()))
+ {
+ return result;
+ }
+ }
+
+ if (result == null)
+ {
+ // This should only happen if there were no search result reference
+ // plugins registered, which is fine.
+ result = SearchReferencePluginResult.SUCCESS;
+ }
+
+ return result;
+ }
/**
* Invokes the set of search result reference plugins that have been
@@ -4626,7 +4784,7 @@
* @return The result of processing the search result reference plugins.
*/
public SearchReferencePluginResult invokeSearchResultReferencePlugins(
- SearchOperation searchOperation,
+ SearchOperationBasis searchOperation,
SearchResultReference searchReference)
{
SearchReferencePluginResult result = null;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/RootDseWorkflowTopology.java b/opendj-sdk/opends/src/server/org/opends/server/core/RootDseWorkflowTopology.java
new file mode 100644
index 0000000..1e526d2
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/RootDseWorkflowTopology.java
@@ -0,0 +1,175 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import org.opends.server.types.DN;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.SearchScope;
+
+
+/**
+ * This class implements the workflow node that handles the root DSE entry.
+ * As opposed to the WorkflowTopologyNode class, the root DSE node has no
+ * parent node nor subordinate nodes. Instead, the root DSE node has a set
+ * of naming contexts, each of which is a WorkflowTopologyNode object with
+ * no parent.
+ */
+public class RootDseWorkflowTopology extends WorkflowTopology
+{
+
+ // The naming contexts known by the root DSE. These naming contexts
+ // are defined in the scope of a network group.
+ private NetworkGroupNamingContexts namingContexts = null;
+
+
+ /**
+ * Creates a workflow node to handle the root DSE entry.
+ *
+ * @param workflowImpl the workflow which contains the processing for
+ * the root DSE backend
+ * @param namingContexts the list of naming contexts being registered
+ * with the network group the root DSE belongs to
+ */
+ public RootDseWorkflowTopology(
+ WorkflowImpl workflowImpl,
+ NetworkGroupNamingContexts namingContexts
+ )
+ {
+ super(workflowImpl);
+ this.namingContexts = namingContexts;
+ }
+
+
+ /**
+ * Executes an operation on the root DSE entry.
+ *
+ * @param operation the operation to execute
+ */
+ public void execute(
+ Operation operation
+ )
+ {
+ // Execute the operation.
+ OperationType operationType = operation.getOperationType();
+ if (operationType != OperationType.SEARCH)
+ {
+ // Execute the operation
+ getWorkflowImpl().execute(operation);
+ }
+ else
+ {
+ // Execute the SEARCH operation
+ executeSearch((SearchOperation) operation);
+ }
+ }
+
+
+ /**
+ * Executes a search operation on the the root DSE entry.
+ *
+ * @param searchOp the operation to execute
+ */
+ private void executeSearch(
+ SearchOperation searchOp
+ )
+ {
+ // Keep a the original search scope because we will alter it in the
+ // operation.
+ SearchScope originalScope = searchOp.getScope();
+
+ // Search base?
+ // The root DSE entry itself is never returned unless the operation
+ // is a search base on the null suffix.
+ if (originalScope == SearchScope.BASE_OBJECT)
+ {
+ getWorkflowImpl().execute(searchOp);
+ return;
+ }
+
+ // Create a workflow result code in case we need to perform search in
+ // subordinate workflows.
+ WorkflowResultCode workflowResultCode = new WorkflowResultCode(
+ searchOp.getResultCode(), searchOp.getErrorMessage());
+
+ // The search scope is not 'base', so let's do a search on all the public
+ // naming contexts with appropriate new search scope and new base DN.
+ SearchScope newScope = elaborateScopeForSearchInSubordinates(originalScope);
+ searchOp.setScope(newScope);
+ DN originalBaseDN = searchOp.getBaseDN();
+
+ for (WorkflowTopologyNode namingContext:
+ namingContexts.getPublicNamingContexts())
+ {
+ // We have to change the operation request base DN to match the
+ // subordinate workflow base DN. Otherwise the workflow will
+ // return a no such entry result code as the operation request
+ // base DN is a superior of the workflow base DN!
+ DN ncDN = namingContext.getBaseDN();
+
+ // Set the new request base DN then do execute the operation
+ // in the naming context workflow.
+ searchOp.setBaseDN(ncDN);
+ namingContext.execute(searchOp);
+ boolean sendReferenceEntry =
+ workflowResultCode.elaborateGlobalResultCode(
+ searchOp.getResultCode(), searchOp.getErrorMessage());
+ if (sendReferenceEntry)
+ {
+ // TODO jdemendi - turn a referral result code into a reference entry
+ // and send the reference entry to the client application
+ }
+ }
+
+ // Now restore the original request base DN and original search scope
+ searchOp.setBaseDN(originalBaseDN);
+ searchOp.setScope(originalScope);
+
+ // Set the operation result code and error message
+ searchOp.setResultCode(workflowResultCode.resultCode());
+ searchOp.setErrorMessage(workflowResultCode.errorMessage());
+ }
+
+
+ /**
+ * Dumps info from the current workflow for debug purpose.
+ *
+ * @param leftMargin white spaces used to indent the traces
+ * @return a string buffer that contains trace information
+ */
+ public StringBuffer toString(String leftMargin)
+ {
+ StringBuffer sb = new StringBuffer();
+
+ // display the baseDN
+ sb.append(leftMargin + "Workflow baseDN:[ \"\" ]\n");
+
+ return sb;
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java
index 007fd1d..80fb4fa 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperation.java
@@ -26,365 +26,29 @@
*/
package org.opends.server.core;
-
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.opends.server.api.Backend;
-import org.opends.server.api.ClientConnection;
-import org.opends.server.api.plugin.PostOperationPluginResult;
-import org.opends.server.api.plugin.PreOperationPluginResult;
-import org.opends.server.api.plugin.PreParsePluginResult;
-import org.opends.server.api.plugin.SearchEntryPluginResult;
-import org.opends.server.api.plugin.SearchReferencePluginResult;
-import org.opends.server.controls.*;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.ldap.LDAPFilter;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
+import org.opends.server.controls.MatchedValuesControl;
import org.opends.server.types.ByteString;
-import org.opends.server.types.CancelledOperationException;
-import org.opends.server.types.CancelRequest;
-import org.opends.server.types.CancelResult;
import org.opends.server.types.Control;
-import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DN;
import org.opends.server.types.DereferencePolicy;
import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DisconnectReason;
-import org.opends.server.types.DN;
import org.opends.server.types.Entry;
-import org.opends.server.types.FilterType;
-import org.opends.server.types.LDAPException;
import org.opends.server.types.Operation;
-import org.opends.server.types.OperationType;
-import org.opends.server.types.Privilege;
import org.opends.server.types.RawFilter;
-import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SearchResultReference;
import org.opends.server.types.SearchScope;
-import org.opends.server.types.operation.PostOperationSearchOperation;
-import org.opends.server.types.operation.PostResponseSearchOperation;
-import org.opends.server.types.operation.PreOperationSearchOperation;
-import org.opends.server.types.operation.PreParseSearchOperation;
-import org.opends.server.types.operation.SearchEntrySearchOperation;
-import org.opends.server.types.operation.SearchReferenceSearchOperation;
-import org.opends.server.util.TimeThread;
-
-import static org.opends.server.core.CoreConstants.*;
-import static org.opends.server.loggers.AccessLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-import static org.opends.server.messages.CoreMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
-
/**
- * This class defines an operation that may be used to locate entries in the
- * Directory Server based on a given set of criteria.
+ * This interface defines an operation used to search for entries
+ * in the Directory Server.
*/
-public class SearchOperation
- extends Operation
- implements PreParseSearchOperation, PreOperationSearchOperation,
- PostOperationSearchOperation, PostResponseSearchOperation,
- SearchEntrySearchOperation, SearchReferenceSearchOperation
+public interface SearchOperation extends Operation
{
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- // Indicates whether a search result done response has been sent to the
- // client.
- private AtomicBoolean responseSent;
-
- // Indicates whether the client is able to handle referrals.
- private boolean clientAcceptsReferrals;
-
- // Indicates whether to include the account usable control with search result
- // entries.
- private boolean includeUsableControl;
-
- // Indicates whether to only real attributes should be returned.
- private boolean realAttributesOnly;
-
- // Indicates whether LDAP subentries should be returned.
- private boolean returnLDAPSubentries;
-
- // Indicates whether to include attribute types only or both types and values.
- private boolean typesOnly;
-
- // Indicates whether to only virtual attributes should be returned.
- private boolean virtualAttributesOnly;
-
- // The raw, unprocessed base DN as included in the request from the client.
- private ByteString rawBaseDN;
-
- // The cancel request that has been issued for this search operation.
- private CancelRequest cancelRequest;
-
- // The dereferencing policy for the search operation.
- private DereferencePolicy derefPolicy;
-
- // The base DN for the search operation.
- private DN baseDN;
-
- // The proxied authorization target DN for this operation.
- private DN proxiedAuthorizationDN;
-
- // The number of entries that have been sent to the client.
- private int entriesSent;
-
- // The number of search result references that have been sent to the client.
- private int referencesSent;
-
- // The size limit for the search operation.
- private int sizeLimit;
-
- // The time limit for the search operation.
- private int timeLimit;
-
- // The set of attributes that should be returned in matching entries.
- private LinkedHashSet<String> attributes;
-
- // The set of response controls for this search operation.
- private List<Control> responseControls;
-
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
- // The time that the search time limit has expired.
- private long timeLimitExpiration;
-
- // The matched values control associated with this search operation.
- private MatchedValuesControl matchedValuesControl;
-
- // The persistent search associated with this search operation.
- private PersistentSearch persistentSearch;
-
- // The raw, unprocessed filter as included in the request from the client.
- private RawFilter rawFilter;
-
- // The search filter for the search operation.
- private SearchFilter filter;
-
- // The search scope for the search operation.
- private SearchScope scope;
-
-
-
- /**
- * Creates a new search operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param rawBaseDN The raw, unprocessed base DN as included in the
- * request from the client.
- * @param scope The scope for this search operation.
- * @param derefPolicy The alias dereferencing policy for this search
- * operation.
- * @param sizeLimit The size limit for this search operation.
- * @param timeLimit The time limit for this search operation.
- * @param typesOnly The typesOnly flag for this search operation.
- * @param rawFilter the raw, unprocessed filter as included in the
- * request from the client.
- * @param attributes The requested attributes for this search
- * operation.
- */
- public SearchOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- ByteString rawBaseDN, SearchScope scope,
- DereferencePolicy derefPolicy, int sizeLimit,
- int timeLimit, boolean typesOnly, RawFilter rawFilter,
- LinkedHashSet<String> attributes)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.rawBaseDN = rawBaseDN;
- this.scope = scope;
- this.derefPolicy = derefPolicy;
- this.sizeLimit = sizeLimit;
- this.timeLimit = timeLimit;
- this.typesOnly = typesOnly;
- this.rawFilter = rawFilter;
-
- if (attributes == null)
- {
- this.attributes = new LinkedHashSet<String>(0);
- }
- else
- {
- this.attributes = attributes;
- }
-
-
- if (clientConnection.getSizeLimit() <= 0)
- {
- this.sizeLimit = sizeLimit;
- }
- else
- {
- if (sizeLimit <= 0)
- {
- this.sizeLimit = clientConnection.getSizeLimit();
- }
- else
- {
- this.sizeLimit = Math.min(sizeLimit, clientConnection.getSizeLimit());
- }
- }
-
-
- if (clientConnection.getTimeLimit() <= 0)
- {
- this.timeLimit = timeLimit;
- }
- else
- {
- if (timeLimit <= 0)
- {
- this.timeLimit = clientConnection.getTimeLimit();
- }
- else
- {
- this.timeLimit = Math.min(timeLimit, clientConnection.getTimeLimit());
- }
- }
-
-
- baseDN = null;
- filter = null;
- entriesSent = 0;
- referencesSent = 0;
- responseControls = new ArrayList<Control>();
- cancelRequest = null;
- clientAcceptsReferrals = true;
- includeUsableControl = false;
- responseSent = new AtomicBoolean(false);
- persistentSearch = null;
- returnLDAPSubentries = false;
- matchedValuesControl = null;
- realAttributesOnly = false;
- virtualAttributesOnly = false;
- }
-
-
-
- /**
- * Creates a new search operation with the provided information.
- *
- * @param clientConnection The client connection with which this operation
- * is associated.
- * @param operationID The operation ID for this operation.
- * @param messageID The message ID of the request with which this
- * operation is associated.
- * @param requestControls The set of controls included in the request.
- * @param baseDN The base DN for this search operation.
- * @param scope The scope for this search operation.
- * @param derefPolicy The alias dereferencing policy for this search
- * operation.
- * @param sizeLimit The size limit for this search operation.
- * @param timeLimit The time limit for this search operation.
- * @param typesOnly The typesOnly flag for this search operation.
- * @param filter The filter for this search operation.
- * @param attributes The attributes for this search operation.
- */
- public SearchOperation(ClientConnection clientConnection, long operationID,
- int messageID, List<Control> requestControls,
- DN baseDN, SearchScope scope,
- DereferencePolicy derefPolicy, int sizeLimit,
- int timeLimit, boolean typesOnly, SearchFilter filter,
- LinkedHashSet<String> attributes)
- {
- super(clientConnection, operationID, messageID, requestControls);
-
-
- this.baseDN = baseDN;
- this.scope = scope;
- this.derefPolicy = derefPolicy;
- this.sizeLimit = sizeLimit;
- this.timeLimit = timeLimit;
- this.typesOnly = typesOnly;
- this.filter = filter;
-
- if (attributes == null)
- {
- this.attributes = new LinkedHashSet<String>(0);
- }
- else
- {
- this.attributes = attributes;
- }
-
- rawBaseDN = new ASN1OctetString(baseDN.toString());
- rawFilter = new LDAPFilter(filter);
-
-
- if (clientConnection.getSizeLimit() <= 0)
- {
- this.sizeLimit = sizeLimit;
- }
- else
- {
- if (sizeLimit <= 0)
- {
- this.sizeLimit = clientConnection.getSizeLimit();
- }
- else
- {
- this.sizeLimit = Math.min(sizeLimit, clientConnection.getSizeLimit());
- }
- }
-
-
- if (clientConnection.getTimeLimit() <= 0)
- {
- this.timeLimit = timeLimit;
- }
- else
- {
- if (timeLimit <= 0)
- {
- this.timeLimit = clientConnection.getTimeLimit();
- }
- else
- {
- this.timeLimit = Math.min(timeLimit, clientConnection.getTimeLimit());
- }
- }
-
-
- entriesSent = 0;
- referencesSent = 0;
- responseControls = new ArrayList<Control>();
- cancelRequest = null;
- clientAcceptsReferrals = true;
- includeUsableControl = false;
- responseSent = new AtomicBoolean(false);
- persistentSearch = null;
- returnLDAPSubentries = false;
- matchedValuesControl = null;
- }
-
-
/**
* Retrieves the raw, unprocessed base DN as included in the request from the
@@ -394,12 +58,7 @@
* @return The raw, unprocessed base DN as included in the request from the
* client.
*/
- public final ByteString getRawBaseDN()
- {
- return rawBaseDN;
- }
-
-
+ public abstract ByteString getRawBaseDN();
/**
* Specifies the raw, unprocessed base DN as included in the request from the
@@ -408,14 +67,7 @@
* @param rawBaseDN The raw, unprocessed base DN as included in the request
* from the client.
*/
- public final void setRawBaseDN(ByteString rawBaseDN)
- {
- this.rawBaseDN = rawBaseDN;
-
- baseDN = null;
- }
-
-
+ public abstract void setRawBaseDN(ByteString rawBaseDN);
/**
* Retrieves the base DN for this search operation. This should not be called
@@ -425,12 +77,7 @@
* @return The base DN for this search operation, or <CODE>null</CODE> if the
* raw base DN has not yet been processed.
*/
- public final DN getBaseDN()
- {
- return baseDN;
- }
-
-
+ public abstract DN getBaseDN();
/**
* Specifies the base DN for this search operation. This method is only
@@ -438,24 +85,14 @@
*
* @param baseDN The base DN for this search operation.
*/
- public final void setBaseDN(DN baseDN)
- {
- this.baseDN = baseDN;
- }
-
-
+ public abstract void setBaseDN(DN baseDN);
/**
* Retrieves the scope for this search operation.
*
* @return The scope for this search operation.
*/
- public final SearchScope getScope()
- {
- return scope;
- }
-
-
+ public abstract SearchScope getScope();
/**
* Specifies the scope for this search operation. This should only be called
@@ -463,24 +100,14 @@
*
* @param scope The scope for this search operation.
*/
- public final void setScope(SearchScope scope)
- {
- this.scope = scope;
- }
-
-
+ public abstract void setScope(SearchScope scope);
/**
* Retrieves the alias dereferencing policy for this search operation.
*
* @return The alias dereferencing policy for this search operation.
*/
- public final DereferencePolicy getDerefPolicy()
- {
- return derefPolicy;
- }
-
-
+ public abstract DereferencePolicy getDerefPolicy();
/**
* Specifies the alias dereferencing policy for this search operation. This
@@ -489,24 +116,14 @@
* @param derefPolicy The alias dereferencing policy for this search
* operation.
*/
- public final void setDerefPolicy(DereferencePolicy derefPolicy)
- {
- this.derefPolicy = derefPolicy;
- }
-
-
+ public abstract void setDerefPolicy(DereferencePolicy derefPolicy);
/**
* Retrieves the size limit for this search operation.
*
* @return The size limit for this search operation.
*/
- public final int getSizeLimit()
- {
- return sizeLimit;
- }
-
-
+ public abstract int getSizeLimit();
/**
* Specifies the size limit for this search operation. This should only be
@@ -514,24 +131,21 @@
*
* @param sizeLimit The size limit for this search operation.
*/
- public final void setSizeLimit(int sizeLimit)
- {
- this.sizeLimit = sizeLimit;
- }
-
-
+ public abstract void setSizeLimit(int sizeLimit);
/**
* Retrieves the time limit for this search operation.
*
* @return The time limit for this search operation.
*/
- public final int getTimeLimit()
- {
- return timeLimit;
- }
+ public abstract int getTimeLimit();
-
+ /**
+ * Get the time after which the search time limit has expired.
+ *
+ * @return the timeLimitExpiration
+ */
+ public abstract Long getTimeLimitExpiration();
/**
* Specifies the time limit for this search operation. This should only be
@@ -539,24 +153,14 @@
*
* @param timeLimit The time limit for this search operation.
*/
- public final void setTimeLimit(int timeLimit)
- {
- this.timeLimit = timeLimit;
- }
-
-
+ public abstract void setTimeLimit(int timeLimit);
/**
* Retrieves the typesOnly flag for this search operation.
*
* @return The typesOnly flag for this search operation.
*/
- public final boolean getTypesOnly()
- {
- return typesOnly;
- }
-
-
+ public abstract boolean getTypesOnly();
/**
* Specifies the typesOnly flag for this search operation. This should only
@@ -564,12 +168,7 @@
*
* @param typesOnly The typesOnly flag for this search operation.
*/
- public final void setTypesOnly(boolean typesOnly)
- {
- this.typesOnly = typesOnly;
- }
-
-
+ public abstract void setTypesOnly(boolean typesOnly);
/**
* Retrieves the raw, unprocessed search filter as included in the request
@@ -580,12 +179,7 @@
* @return The raw, unprocessed search filter as included in the request from
* the client.
*/
- public final RawFilter getRawFilter()
- {
- return rawFilter;
- }
-
-
+ public abstract RawFilter getRawFilter();
/**
* Specifies the raw, unprocessed search filter as included in the request
@@ -594,14 +188,7 @@
* @param rawFilter The raw, unprocessed search filter as included in the
* request from the client.
*/
- public final void setRawFilter(RawFilter rawFilter)
- {
- this.rawFilter = rawFilter;
-
- filter = null;
- }
-
-
+ public abstract void setRawFilter(RawFilter rawFilter);
/**
* Retrieves the filter for this search operation. This should not be called
@@ -611,12 +198,7 @@
* @return The filter for this search operation, or <CODE>null</CODE> if the
* raw filter has not yet been processed.
*/
- public final SearchFilter getFilter()
- {
- return filter;
- }
-
-
+ public abstract SearchFilter getFilter();
/**
* Retrieves the set of requested attributes for this search operation. Its
@@ -624,12 +206,7 @@
*
* @return The set of requested attributes for this search operation.
*/
- public final LinkedHashSet<String> getAttributes()
- {
- return attributes;
- }
-
-
+ public abstract LinkedHashSet<String> getAttributes();
/**
* Specifies the set of requested attributes for this search operation. It
@@ -638,19 +215,7 @@
* @param attributes The set of requested attributes for this search
* operation.
*/
- public final void setAttributes(LinkedHashSet<String> attributes)
- {
- if (attributes == null)
- {
- this.attributes.clear();
- }
- else
- {
- this.attributes = attributes;
- }
- }
-
-
+ public abstract void setAttributes(LinkedHashSet<String> attributes);
/**
* Retrieves the number of entries sent to the client for this search
@@ -659,12 +224,7 @@
* @return The number of entries sent to the client for this search
* operation.
*/
- public final int getEntriesSent()
- {
- return entriesSent;
- }
-
-
+ public abstract int getEntriesSent();
/**
* Retrieves the number of search references sent to the client for this
@@ -673,45 +233,7 @@
* @return The number of search references sent to the client for this search
* operation.
*/
- public final int getReferencesSent()
- {
- return referencesSent;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
+ public abstract int getReferencesSent();
/**
* Used as a callback for backends to indicate that the provided entry matches
@@ -728,439 +250,7 @@
* <CODE>false</CODE> if not for some reason (e.g., the size limit
* has been reached or the search has been abandoned).
*/
- public final boolean returnEntry(Entry entry, List<Control> controls)
- {
- // See if the operation has been abandoned. If so, then don't send the
- // entry and indicate that the search should end.
- if (cancelRequest != null)
- {
- setResultCode(ResultCode.CANCELED);
- return false;
- }
-
- // See if the size limit has been exceeded. If so, then don't send the
- // entry and indicate that the search should end.
- if ((sizeLimit > 0) && (entriesSent >= sizeLimit))
- {
- setResultCode(ResultCode.SIZE_LIMIT_EXCEEDED);
- appendErrorMessage(getMessage(MSGID_SEARCH_SIZE_LIMIT_EXCEEDED,
- sizeLimit));
- return false;
- }
-
- // See if the time limit has expired. If so, then don't send the entry and
- // indicate that the search should end.
- if ((timeLimit > 0) && (TimeThread.getTime() >= timeLimitExpiration))
- {
- setResultCode(ResultCode.TIME_LIMIT_EXCEEDED);
- appendErrorMessage(getMessage(MSGID_SEARCH_TIME_LIMIT_EXCEEDED,
- timeLimit));
- return false;
- }
-
- // Determine whether the provided entry is a subentry and if so whether it
- // should be returned.
- if ((scope != SearchScope.BASE_OBJECT) && (! returnLDAPSubentries) &&
- entry.isLDAPSubentry())
- {
- // Check to see if the filter contains an equality element with the
- // objectclass attribute type and a value of "ldapSubentry". If so, then
- // we'll return it anyway. Technically, this isn't part of the
- // specification so we don't need to get carried away with really in-depth
- // checks.
- switch (filter.getFilterType())
- {
- case AND:
- case OR:
- for (SearchFilter f : filter.getFilterComponents())
- {
- if ((f.getFilterType() == FilterType.EQUALITY) &&
- (f.getAttributeType().isObjectClassType()))
- {
- AttributeValue v = f.getAssertionValue();
- if (toLowerCase(v.getStringValue()).equals("ldapsubentry"))
- {
- returnLDAPSubentries = true;
- }
- break;
- }
- }
- break;
- case EQUALITY:
- AttributeType t = filter.getAttributeType();
- if (t.isObjectClassType())
- {
- AttributeValue v = filter.getAssertionValue();
- if (toLowerCase(v.getStringValue()).equals("ldapsubentry"))
- {
- returnLDAPSubentries = true;
- }
- }
- break;
- }
-
- if (! returnLDAPSubentries)
- {
- // We still shouldn't return it even based on the filter. Just throw it
- // away without doing anything.
- return true;
- }
- }
-
-
- // Determine whether to include the account usable control. If so, then
- // create it now.
- if (includeUsableControl)
- {
- try
- {
- // FIXME -- Need a way to enable PWP debugging.
- PasswordPolicyState pwpState = new PasswordPolicyState(entry, false,
- false);
-
- boolean isInactive = pwpState.isDisabled() ||
- pwpState.isAccountExpired();
- boolean isLocked = pwpState.lockedDueToFailures() ||
- pwpState.lockedDueToMaximumResetAge() ||
- pwpState.lockedDueToIdleInterval();
- boolean isReset = pwpState.mustChangePassword();
- boolean isExpired = pwpState.isPasswordExpired();
-
- if (isInactive || isLocked || isReset || isExpired)
- {
- int secondsBeforeUnlock = pwpState.getSecondsUntilUnlock();
- int remainingGraceLogins = pwpState.getGraceLoginsRemaining();
-
- if (controls == null)
- {
- controls = new ArrayList<Control>(1);
- }
-
- controls.add(new AccountUsableResponseControl(isInactive, isReset,
- isExpired, remainingGraceLogins, isLocked,
- secondsBeforeUnlock));
- }
- else
- {
- if (controls == null)
- {
- controls = new ArrayList<Control>(1);
- }
-
- int secondsBeforeExpiration = pwpState.getSecondsUntilExpiration();
- controls.add(new AccountUsableResponseControl(
- secondsBeforeExpiration));
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- }
-
- // Check to see if the entry can be read by the client.
- SearchResultEntry tmpSearchEntry = new SearchResultEntry(entry,
- controls);
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().maySend(this, tmpSearchEntry) == false) {
- return true;
- }
-
- // Make a copy of the entry and pare it down to only include the set
- // of
- // requested attributes.
- Entry entryToReturn;
- if ((attributes == null) || attributes.isEmpty())
- {
- entryToReturn = entry.duplicateWithoutOperationalAttributes(typesOnly,
- true);
- }
- else
- {
- entryToReturn = entry.duplicateWithoutAttributes();
-
- for (String attrName : attributes)
- {
- if (attrName.equals("*"))
- {
- // This is a special placeholder indicating that all user attributes
- // should be returned.
- if (typesOnly)
- {
- // First, add the placeholder for the objectclass attribute.
- AttributeType ocType =
- DirectoryServer.getObjectClassAttributeType();
- List<Attribute> ocList = new ArrayList<Attribute>(1);
- ocList.add(new Attribute(ocType));
- entryToReturn.putAttribute(ocType, ocList);
- }
- else
- {
- // First, add the objectclass attribute.
- Attribute ocAttr = entry.getObjectClassAttribute();
- try
- {
- entryToReturn.setObjectClasses(ocAttr.getValues());
- }
- catch (DirectoryException e)
- {
- // We cannot get this exception because the object classes have
- // already been validated in the entry they came from.
- }
- }
-
- // Next iterate through all the user attributes and include them.
- for (AttributeType t : entry.getUserAttributes().keySet())
- {
- List<Attribute> attrList =
- entry.duplicateUserAttribute(t, null, typesOnly);
- entryToReturn.putAttribute(t, attrList);
- }
-
- continue;
- }
- else if (attrName.equals("+"))
- {
- // This is a special placeholder indicating that all operational
- // attributes should be returned.
- for (AttributeType t : entry.getOperationalAttributes().keySet())
- {
- List<Attribute> attrList =
- entry.duplicateOperationalAttribute(t, null, typesOnly);
- entryToReturn.putAttribute(t, attrList);
- }
-
- continue;
- }
-
- String lowerName;
- HashSet<String> options;
- int semicolonPos = attrName.indexOf(';');
- if (semicolonPos > 0)
- {
- lowerName = toLowerCase(attrName.substring(0, semicolonPos));
- int nextPos = attrName.indexOf(';', semicolonPos+1);
- options = new HashSet<String>();
- while (nextPos > 0)
- {
- options.add(attrName.substring(semicolonPos+1, nextPos));
-
- semicolonPos = nextPos;
- nextPos = attrName.indexOf(';', semicolonPos+1);
- }
-
- options.add(attrName.substring(semicolonPos+1));
- }
- else
- {
- lowerName = toLowerCase(attrName);
- options = null;
- }
-
-
- AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
- if (attrType == null)
- {
- boolean added = false;
- for (AttributeType t : entry.getUserAttributes().keySet())
- {
- if (t.hasNameOrOID(lowerName))
- {
- List<Attribute> attrList =
- entry.duplicateUserAttribute(t, options, typesOnly);
- if (attrList != null)
- {
- entryToReturn.putAttribute(t, attrList);
-
- added = true;
- break;
- }
- }
- }
-
- if (added)
- {
- continue;
- }
-
- for (AttributeType t : entry.getOperationalAttributes().keySet())
- {
- if (t.hasNameOrOID(lowerName))
- {
- List<Attribute> attrList =
- entry.duplicateOperationalAttribute(t, options, typesOnly);
- if (attrList != null)
- {
- entryToReturn.putAttribute(t, attrList);
-
- break;
- }
- }
- }
- }
- else
- {
- if (attrType.isObjectClassType()) {
- if (typesOnly)
- {
- AttributeType ocType =
- DirectoryServer.getObjectClassAttributeType();
- List<Attribute> ocList = new ArrayList<Attribute>(1);
- ocList.add(new Attribute(ocType));
- entryToReturn.putAttribute(ocType, ocList);
- }
- else
- {
- List<Attribute> attrList = new ArrayList<Attribute>(1);
- attrList.add(entry.getObjectClassAttribute());
- entryToReturn.putAttribute(attrType, attrList);
- }
- }
- else
- {
- List<Attribute> attrList =
- entry.duplicateOperationalAttribute(attrType, options,
- typesOnly);
- if (attrList == null)
- {
- attrList = entry.duplicateUserAttribute(attrType, options,
- typesOnly);
- }
- if (attrList != null)
- {
- entryToReturn.putAttribute(attrType, attrList);
- }
- }
- }
- }
- }
-
-
- if (realAttributesOnly)
- {
- entryToReturn.stripVirtualAttributes();
- }
- else if (virtualAttributesOnly)
- {
- entryToReturn.stripRealAttributes();
- }
-
-
- // If there is a matched values control, then further pare down the entry
- // based on the filters that it contains.
- if ((matchedValuesControl != null) && (! typesOnly))
- {
- // First, look at the set of objectclasses.
- AttributeType attrType = DirectoryServer.getObjectClassAttributeType();
- Iterator<String> ocIterator =
- entryToReturn.getObjectClasses().values().iterator();
- while (ocIterator.hasNext())
- {
- String ocName = ocIterator.next();
- AttributeValue v = new AttributeValue(attrType,
- new ASN1OctetString(ocName));
- if (! matchedValuesControl.valueMatches(attrType, v))
- {
- ocIterator.remove();
- }
- }
-
-
- // Next, the set of user attributes.
- for (AttributeType t : entryToReturn.getUserAttributes().keySet())
- {
- for (Attribute a : entryToReturn.getUserAttribute(t))
- {
- Iterator<AttributeValue> valueIterator = a.getValues().iterator();
- while (valueIterator.hasNext())
- {
- AttributeValue v = valueIterator.next();
- if (! matchedValuesControl.valueMatches(t, v))
- {
- valueIterator.remove();
- }
- }
- }
- }
-
-
- // Then the set of operational attributes.
- for (AttributeType t : entryToReturn.getOperationalAttributes().keySet())
- {
- for (Attribute a : entryToReturn.getOperationalAttribute(t))
- {
- Iterator<AttributeValue> valueIterator = a.getValues().iterator();
- while (valueIterator.hasNext())
- {
- AttributeValue v = valueIterator.next();
- if (! matchedValuesControl.valueMatches(t, v))
- {
- valueIterator.remove();
- }
- }
- }
- }
- }
-
-
- // Convert the provided entry to a search result entry.
- SearchResultEntry searchEntry = new SearchResultEntry(entryToReturn,
- controls);
-
- // Strip out any attributes that the client does not have access to.
-
- // FIXME: need some way to prevent plugins from adding attributes or
- // values that the client is not permitted to see.
- searchEntry = AccessControlConfigManager.getInstance()
- .getAccessControlHandler().filterEntry(this, searchEntry);
-
- // Invoke any search entry plugins that may be registered with the server.
- SearchEntryPluginResult pluginResult =
- DirectoryServer.getPluginConfigManager().
- invokeSearchResultEntryPlugins(this, searchEntry);
- if (pluginResult.connectionTerminated())
- {
- // We won't attempt to send this entry, and we won't continue with
- // any processing. Just update the operation to indicate that it was
- // cancelled and return false.
- setResultCode(ResultCode.CANCELED);
- appendErrorMessage(getMessage(MSGID_CANCELED_BY_SEARCH_ENTRY_DISCONNECT,
- String.valueOf(entry.getDN())));
- return false;
- }
-
-
- // Send the entry to the client.
- if (pluginResult.sendEntry())
- {
- try
- {
- clientConnection.sendSearchEntry(this, searchEntry);
-
- // Log the entry sent to the client.
- logSearchResultEntry(this, searchEntry);
-
- entriesSent++;
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResponseData(de);
- return false;
- }
- }
-
- return pluginResult.continueSearch();
- }
-
-
+ public abstract boolean returnEntry(Entry entry, List<Control> controls);
/**
* Used as a callback for backends to indicate that the provided search
@@ -1174,100 +264,7 @@
* <CODE>false</CODE> if not for some reason (e.g., the size limit
* has been reached or the search has been abandoned).
*/
- public final boolean returnReference(SearchResultReference reference)
- {
- // See if the operation has been abandoned. If so, then don't send the
- // reference and indicate that the search should end.
- if (cancelRequest != null)
- {
- setResultCode(ResultCode.CANCELED);
- return false;
- }
-
-
- // See if the time limit has expired. If so, then don't send the entry and
- // indicate that the search should end.
- if ((timeLimit > 0) && (TimeThread.getTime() >= timeLimitExpiration))
- {
- setResultCode(ResultCode.TIME_LIMIT_EXCEEDED);
- appendErrorMessage(getMessage(MSGID_SEARCH_TIME_LIMIT_EXCEEDED,
- timeLimit));
- return false;
- }
-
-
- // See if we know that this client can't handle referrals. If so, then
- // don't even try to send it.
- if (! clientAcceptsReferrals)
- {
- return true;
- }
-
-
- // See if the client has permission to read this reference.
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().maySend(this, reference) == false) {
- return true;
- }
-
-
- // Invoke any search reference plugins that may be registered with the
- // server.
- SearchReferencePluginResult pluginResult =
- DirectoryServer.getPluginConfigManager().
- invokeSearchResultReferencePlugins(this, reference);
- if (pluginResult.connectionTerminated())
- {
- // We won't attempt to send this entry, and we won't continue with
- // any processing. Just update the operation to indicate that it was
- // cancelled and return false.
- setResultCode(ResultCode.CANCELED);
- appendErrorMessage(getMessage(MSGID_CANCELED_BY_SEARCH_REF_DISCONNECT,
- String.valueOf(reference.getReferralURLString())));
- return false;
- }
-
-
- // Send the reference to the client. Note that this could throw an
- // exception, which would indicate that the associated client can't handle
- // referrals. If that't the case, then set a flag so we'll know not to try
- // to send any more.
- if (pluginResult.sendReference())
- {
- try
- {
- if (clientConnection.sendSearchReference(this, reference))
- {
- // Log the entry sent to the client.
- logSearchResultReference(this, reference);
- referencesSent++;
-
- // FIXME -- Should the size limit apply here?
- }
- else
- {
- // We know that the client can't handle referrals, so we won't try to
- // send it any more.
- clientAcceptsReferrals = false;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResponseData(de);
- return false;
- }
- }
-
-
- return pluginResult.continueSearch();
- }
-
-
+ public abstract boolean returnReference(SearchResultReference reference);
/**
* Sends the search result done message to the client. Note that this method
@@ -1277,174 +274,182 @@
* message should have been set for this operation before this method is
* called.
*/
- public final void sendSearchResultDone()
- {
- // Send the search result done message to the client. We want to make sure
- // that this only gets sent once, and it's possible that this could be
- // multithreaded in the event of a persistent search, so do it safely.
- if (responseSent.compareAndSet(false, true))
- {
- // Send the response to the client.
- clientConnection.sendResponse(this);
-
- // Log the search result.
- logSearchResultDone(this);
-
-
- // Invoke the post-response search plugins.
- DirectoryServer.getPluginConfigManager().
- invokePostResponseSearchPlugins(this);
- }
- }
-
-
+ public abstract void sendSearchResultDone();
/**
- * {@inheritDoc}
+ * Set the time after which the search time limit has expired.
+ *
+ * @param timeLimitExpiration - Time after which the search has expired
*/
- @Override()
- public final OperationType getOperationType()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- return OperationType.SEARCH;
- }
-
-
+ public abstract void setTimeLimitExpiration(Long timeLimitExpiration);
/**
- * {@inheritDoc}
+ * Indicates whether LDAP subentries should be returned or not.
+ *
+ * @return true if the LDAP subentries should be returned, false otherwise
*/
- @Override()
- public final void disconnectClient(DisconnectReason disconnectReason,
- boolean sendNotification, String message,
- int messageID)
- {
- // Before calling clientConnection.disconnect, we need to mark this
- // operation as cancelled so that the attempt to cancel it later won't cause
- // an unnecessary delay.
- setCancelResult(CancelResult.CANCELED);
-
- clientConnection.disconnect(disconnectReason, sendNotification, message,
- messageID);
- }
-
-
+ public abstract boolean isReturnLDAPSubentries();
/**
- * {@inheritDoc}
+ * Set the flag indicating wether the LDAP subentries should be returned.
+ *
+ * @param returnLDAPSubentries - Boolean indicating wether the LDAP
+ * subentries should be returned or not
*/
- @Override()
- public final String[][] getRequestLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
-
- String attrs;
- if ((attributes == null) || attributes.isEmpty())
- {
- attrs = null;
- }
- else
- {
- StringBuilder attrBuffer = new StringBuilder();
- Iterator<String> iterator = attributes.iterator();
- attrBuffer.append(iterator.next());
-
- while (iterator.hasNext())
- {
- attrBuffer.append(", ");
- attrBuffer.append(iterator.next());
- }
-
- attrs = attrBuffer.toString();
- }
-
- return new String[][]
- {
- new String[] { LOG_ELEMENT_BASE_DN, String.valueOf(rawBaseDN) },
- new String[] { LOG_ELEMENT_SCOPE, String.valueOf(scope) },
- new String[] { LOG_ELEMENT_SIZE_LIMIT, String.valueOf(sizeLimit) },
- new String[] { LOG_ELEMENT_TIME_LIMIT, String.valueOf(timeLimit) },
- new String[] { LOG_ELEMENT_FILTER, String.valueOf(rawFilter) },
- new String[] { LOG_ELEMENT_REQUESTED_ATTRIBUTES, attrs }
- };
- }
-
-
+ public abstract void setReturnLDAPSubentries(boolean returnLDAPSubentries);
/**
- * {@inheritDoc}
+ * The matched values control associated with this search operation.
+ *
+ * @return the match values control
*/
- @Override()
- public final String[][] getResponseLogElements()
- {
- // Note that no debugging will be done in this method because it is a likely
- // candidate for being called by the logging subsystem.
+ public abstract MatchedValuesControl getMatchedValuesControl();
- String resultCode = String.valueOf(getResultCode().getIntValue());
+ /**
+ * Set the match values control.
+ *
+ * @param controls - The matched values control
+ */
+ public abstract void setMatchedValuesControl(MatchedValuesControl controls);
- String errorMessage;
- StringBuilder errorMessageBuffer = getErrorMessage();
- if (errorMessageBuffer == null)
- {
- errorMessage = null;
- }
- else
- {
- errorMessage = errorMessageBuffer.toString();
- }
+ /**
+ * Indicates whether to include the account usable response control with
+ * search result entries or not.
+ *
+ * @return true if the usable control has to be part of the search result
+ * entry
+ */
+ public abstract boolean isIncludeUsableControl();
- String matchedDNStr;
- DN matchedDN = getMatchedDN();
- if (matchedDN == null)
- {
- matchedDNStr = null;
- }
- else
- {
- matchedDNStr = matchedDN.toString();
- }
+ /**
+ * Specify whether to include the account usable response control within the
+ * search result entries.
+ *
+ * @param includeUsableControl - True if the account usable response control
+ * has to be included within the search result
+ * entries, false otherwise
+ */
+ public abstract void setIncludeUsableControl(boolean includeUsableControl);
- String referrals;
- List<String> referralURLs = getReferralURLs();
- if ((referralURLs == null) || referralURLs.isEmpty())
- {
- referrals = null;
- }
- else
- {
- StringBuilder buffer = new StringBuilder();
- Iterator<String> iterator = referralURLs.iterator();
- buffer.append(iterator.next());
+ /**
+ * Register the psearch in the search operation.
+ *
+ * @param psearch - Persistent search associated to that operation
+ */
+ public abstract void setPersistentSearch(PersistentSearch psearch);
- while (iterator.hasNext())
- {
- buffer.append(", ");
- buffer.append(iterator.next());
- }
+ /**
+ * Get the psearch from the search operation.
+ *
+ * @return the psearch, or null if no psearch was registered
+ */
+ public abstract PersistentSearch getPersistentSearch();
- referrals = buffer.toString();
- }
+ /**
+ * Indicates whether the client is able to handle referrals.
+ *
+ * @return true, if the client is able to handle referrals
+ */
+ public abstract boolean isClientAcceptsReferrals();
- String processingTime =
- String.valueOf(processingStopTime - processingStartTime);
+ /**
+ * Specify whether the client is able to handle referrals.
+ *
+ * @param clientAcceptReferrals - Boolean set to true if the client
+ * can handle referrals
+ */
+ public abstract void setClientAcceptsReferrals(boolean clientAcceptReferrals);
- return new String[][]
- {
- new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
- new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
- new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
- new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
- new String[] { LOG_ELEMENT_ENTRIES_SENT, String.valueOf(entriesSent) },
- new String[] { LOG_ELEMENT_REFERENCES_SENT,
- String.valueOf(referencesSent ) },
- new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
- };
- }
+ /**
+ * Increments by 1 the number of entries sent to the client for this search
+ * operation.
+ */
+ public abstract void incrementEntriesSent();
+ /**
+ * Increments by 1 the number of search references sent to the client for this
+ * search operation.
+ */
+ public abstract void incrementReferencesSent();
+ /**
+ * Indicates wether the search result done message has to be sent
+ * to the client, or not.
+ *
+ * @return true if the search result done message is to be sent to the client
+ */
+ public abstract boolean isSendResponse();
+
+ /**
+ * Specify wether the search result done message has to be sent
+ * to the client, or not.
+ *
+ * @param sendResponse - boolean indicating wether the search result done
+ * message is to send to the client
+ */
+ public abstract void setSendResponse(boolean sendResponse);
+
+ /**
+ * Returns true if only real attributes should be returned.
+ *
+ * @return true if only real attributes should be returned, false otherwise
+ */
+ public abstract boolean isRealAttributesOnly();
+
+ /**
+ * Specify wether to only return real attributes.
+ *
+ * @param realAttributesOnly - boolean setup to true, if only the real
+ * attributes should be returned
+ */
+ public abstract void setRealAttributesOnly(boolean realAttributesOnly);
+
+ /**
+ * Returns true if only virtual attributes should be returned.
+ *
+ * @return true if only virtual attributes should be returned, false
+ * otherwise
+ */
+ public abstract boolean isVirtualAttributesOnly();
+
+ /**
+ * Specify wether to only return virtual attributes.
+ *
+ * @param virtualAttributesOnly - boolean setup to true, if only the virtual
+ * attributes should be returned
+ */
+ public abstract void setVirtualAttributesOnly(boolean virtualAttributesOnly);
+
+ /**
+ * Sends the provided search result entry to the client.
+ *
+ * @param entry The search result entry to be sent to
+ * the client.
+ *
+ * @throws DirectoryException If a problem occurs while attempting
+ * to send the entry to the client and
+ * the search should be terminated.
+ */
+ public abstract void sendSearchEntry(SearchResultEntry entry)
+ throws DirectoryException;
+
+ /**
+ * Sends the provided search result reference to the client.
+ *
+ * @param reference The search result reference to be sent
+ * to the client.
+ *
+ * @return <CODE>true</CODE> if the client is able to accept
+ * referrals, or <CODE>false</CODE> if the client cannot
+ * handle referrals and no more attempts should be made to
+ * send them for the associated search operation.
+ *
+ * @throws DirectoryException If a problem occurs while attempting
+ * to send the reference to the client
+ * and the search should be terminated.
+ */
+ public abstract boolean sendSearchReference(SearchResultReference reference)
+ throws DirectoryException;
/**
* Retrieves the proxied authorization DN for this operation if proxied
@@ -1454,938 +459,17 @@
* authorization has been requested, or {@code null} if proxied
* authorization has not been requested.
*/
- public DN getProxiedAuthorizationDN()
- {
- return proxiedAuthorizationDN;
- }
-
-
+ public abstract DN getProxiedAuthorizationDN();
/**
- * {@inheritDoc}
- */
- @Override()
- public final List<Control> getResponseControls()
- {
- return responseControls;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void addResponseControl(Control control)
- {
- responseControls.add(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void removeResponseControl(Control control)
- {
- responseControls.remove(control);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void run()
- {
- setResultCode(ResultCode.UNDEFINED);
- boolean sendResponse = true;
-
-
- // Get the plugin config manager that will be used for invoking plugins.
- PluginConfigManager pluginConfigManager =
- DirectoryServer.getPluginConfigManager();
- boolean skipPostOperation = false;
-
-
- // Start the processing timer.
- processingStartTime = System.currentTimeMillis();
- if (timeLimit <= 0)
- {
- timeLimitExpiration = Long.MAX_VALUE;
- }
- else
- {
- // FIXME -- Factor in the user's effective time limit.
- timeLimitExpiration = processingStartTime + (1000L * timeLimit);
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- return;
- }
-
-
- // Create a labeled block of code that we can break out of if a problem is
- // detected.
-searchProcessing:
- {
- PreParsePluginResult preParseResult =
- pluginConfigManager.invokePreParseSearchPlugins(this);
- if (preParseResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the request and
- // result and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
-
- logSearchRequest(this);
- logSearchResultDone(this);
- pluginConfigManager.invokePostResponseSearchPlugins(this);
- return;
- }
- else if (preParseResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- logSearchRequest(this);
- break searchProcessing;
- }
- else if (preParseResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break searchProcessing;
- }
-
-
- // Log the search request message.
- logSearchRequest(this);
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logSearchResultDone(this);
- pluginConfigManager.invokePostResponseSearchPlugins(this);
- return;
- }
-
-
- // Process the search base and filter to convert them from their raw forms
- // as provided by the client to the forms required for the rest of the
- // search processing.
- try
- {
- if (baseDN == null)
- {
- baseDN = DN.decode(rawBaseDN);
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break searchProcessing;
- }
-
- try
- {
- if (filter == null)
- {
- filter = rawFilter.toSearchFilter();
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- break searchProcessing;
- }
-
- // Check to see if there are any controls in the request. If so, then
- // see if there is any special processing required.
- boolean processSearch = true;
- List<Control> requestControls = getRequestControls();
- if ((requestControls != null) && (! requestControls.isEmpty()))
- {
- for (int i=0; i < requestControls.size(); i++)
- {
- Control c = requestControls.get(i);
- String oid = c.getOID();
-
- if (oid.equals(OID_LDAP_ASSERTION))
- {
- LDAPAssertionRequestControl assertControl;
- if (c instanceof LDAPAssertionRequestControl)
- {
- assertControl = (LDAPAssertionRequestControl) c;
- }
- else
- {
- try
- {
- assertControl = LDAPAssertionRequestControl.decodeControl(c);
- requestControls.set(i, assertControl);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break searchProcessing;
- }
- }
-
- try
- {
- // FIXME -- We need to determine whether the current user has
- // permission to make this determination.
- SearchFilter assertionFilter = assertControl.getSearchFilter();
- Entry entry;
- try
- {
- entry = DirectoryServer.getEntry(baseDN);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
-
- int msgID = MSGID_SEARCH_CANNOT_GET_ENTRY_FOR_ASSERTION;
- appendErrorMessage(getMessage(msgID, de.getErrorMessage()));
-
- break searchProcessing;
- }
-
- if (entry == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
-
- int msgID = MSGID_SEARCH_NO_SUCH_ENTRY_FOR_ASSERTION;
- appendErrorMessage(getMessage(msgID));
-
- break searchProcessing;
- }
-
-
- if (! assertionFilter.matchesEntry(entry))
- {
- setResultCode(ResultCode.ASSERTION_FAILED);
-
- appendErrorMessage(getMessage(MSGID_SEARCH_ASSERTION_FAILED));
-
- break searchProcessing;
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(ResultCode.PROTOCOL_ERROR);
-
- int msgID = MSGID_SEARCH_CANNOT_PROCESS_ASSERTION_FILTER;
- appendErrorMessage(getMessage(msgID, de.getErrorMessage()));
-
- break searchProcessing;
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V1))
- {
- // The requester must have the PROXIED_AUTH privilige in order to be
- // able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break searchProcessing;
- }
-
-
- ProxiedAuthV1Control proxyControl;
- if (c instanceof ProxiedAuthV1Control)
- {
- proxyControl = (ProxiedAuthV1Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV1Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break searchProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break searchProcessing;
- }
-
- if (AccessControlConfigManager.getInstance().
- getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_SEARCH_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(baseDN)));
-
- skipPostOperation = true;
- break searchProcessing;
- }
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
- else if (oid.equals(OID_PROXIED_AUTH_V2))
- {
- // The requester must have the PROXIED_AUTH privilige in order to be
- // able to use this control.
- if (! clientConnection.hasPrivilege(Privilege.PROXIED_AUTH, this))
- {
- int msgID = MSGID_PROXYAUTH_INSUFFICIENT_PRIVILEGES;
- appendErrorMessage(getMessage(msgID));
- setResultCode(ResultCode.AUTHORIZATION_DENIED);
- break searchProcessing;
- }
-
-
- ProxiedAuthV2Control proxyControl;
- if (c instanceof ProxiedAuthV2Control)
- {
- proxyControl = (ProxiedAuthV2Control) c;
- }
- else
- {
- try
- {
- proxyControl = ProxiedAuthV2Control.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break searchProcessing;
- }
- }
-
-
- Entry authorizationEntry;
- try
- {
- authorizationEntry = proxyControl.getAuthorizationEntry();
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
-
- break searchProcessing;
- }
-
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isProxiedAuthAllowed(this,
- authorizationEntry) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_SEARCH_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(baseDN)));
-
- skipPostOperation = true;
- break searchProcessing;
- }
-
- setAuthorizationEntry(authorizationEntry);
- if (authorizationEntry == null)
- {
- proxiedAuthorizationDN = DN.nullDN();
- }
- else
- {
- proxiedAuthorizationDN = authorizationEntry.getDN();
- }
- }
- else if (oid.equals(OID_PERSISTENT_SEARCH))
- {
- PersistentSearchControl psearchControl;
- if (c instanceof PersistentSearchControl)
- {
- psearchControl = (PersistentSearchControl) c;
- }
- else
- {
- try
- {
- psearchControl = PersistentSearchControl.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break searchProcessing;
- }
- }
-
- persistentSearch =
- new PersistentSearch(this, psearchControl.getChangeTypes(),
- psearchControl.getReturnECs());
-
- // If we're only interested in changes, then we don't actually want
- // to process the search now.
- if (psearchControl.getChangesOnly())
- {
- processSearch = false;
- }
- }
- else if (oid.equals(OID_LDAP_SUBENTRIES))
- {
- returnLDAPSubentries = true;
- }
- else if (oid.equals(OID_MATCHED_VALUES))
- {
- if (c instanceof MatchedValuesControl)
- {
- matchedValuesControl = (MatchedValuesControl) c;
- }
- else
- {
- try
- {
- matchedValuesControl = MatchedValuesControl.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break searchProcessing;
- }
- }
- }
- else if (oid.equals(OID_ACCOUNT_USABLE_CONTROL))
- {
- includeUsableControl = true;
- }
- else if (oid.equals(OID_REAL_ATTRS_ONLY))
- {
- realAttributesOnly = true;
- }
- else if (oid.equals(OID_VIRTUAL_ATTRS_ONLY))
- {
- virtualAttributesOnly = true;
- } else if(oid.equals(OID_GET_EFFECTIVE_RIGHTS)) {
- GetEffectiveRights effectiveRightsControl;
- if (c instanceof GetEffectiveRights)
- {
- effectiveRightsControl = (GetEffectiveRights) c;
- }
- else
- {
- try
- {
- effectiveRightsControl = GetEffectiveRights.decodeControl(c);
- }
- catch (LDAPException le)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, le);
- }
-
- setResultCode(ResultCode.valueOf(le.getResultCode()));
- appendErrorMessage(le.getMessage());
-
- break searchProcessing;
- }
- }
-
- if (!AccessControlConfigManager.getInstance()
- .getAccessControlHandler().
- isGetEffectiveRightsAllowed(this, effectiveRightsControl)) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
- int msgID =
- MSGID_SEARCH_EFFECTIVERIGHTS_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(baseDN)));
-
- skipPostOperation = true;
- break searchProcessing;
- }
- }
-
- // NYI -- Add support for additional controls.
- else if (c.isCritical())
- {
- Backend backend = DirectoryServer.getBackend(baseDN);
- if ((backend == null) || (! backend.supportsControl(oid)))
- {
- setResultCode(ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
-
- int msgID = MSGID_SEARCH_UNSUPPORTED_CRITICAL_CONTROL;
- appendErrorMessage(getMessage(msgID, oid));
-
- break searchProcessing;
- }
- }
- }
- }
-
-
- // Check to see if the client has permission to perform the
- // search.
-
- // FIXME: for now assume that this will check all permission
- // pertinent to the operation. This includes proxy authorization
- // and any other controls specified.
- if (AccessControlConfigManager.getInstance()
- .getAccessControlHandler().isAllowed(this) == false) {
- setResultCode(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
- int msgID = MSGID_SEARCH_AUTHZ_INSUFFICIENT_ACCESS_RIGHTS;
- appendErrorMessage(getMessage(msgID, String.valueOf(baseDN)));
-
- skipPostOperation = true;
- break searchProcessing;
- }
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logSearchResultDone(this);
- pluginConfigManager.invokePostResponseSearchPlugins(this);
- return;
- }
-
-
- // Invoke the pre-operation search plugins.
- PreOperationPluginResult preOpResult =
- pluginConfigManager.invokePreOperationSearchPlugins(this);
- if (preOpResult.connectionTerminated())
- {
- // There's no point in continuing with anything. Log the request and
- // result and return.
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_PREOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
- logSearchResultDone(this);
- pluginConfigManager.invokePostResponseSearchPlugins(this);
- return;
- }
- else if (preOpResult.sendResponseImmediately())
- {
- skipPostOperation = true;
- break searchProcessing;
- }
- else if (preOpResult.skipCoreProcessing())
- {
- skipPostOperation = false;
- break searchProcessing;
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logSearchResultDone(this);
- pluginConfigManager.invokePostResponseSearchPlugins(this);
- return;
- }
-
-
- // Get the backend that should hold the search base. If there is none,
- // then fail.
- Backend backend = DirectoryServer.getBackend(baseDN);
- if (backend == null)
- {
- setResultCode(ResultCode.NO_SUCH_OBJECT);
- appendErrorMessage(getMessage(MSGID_SEARCH_BASE_DOESNT_EXIST,
- String.valueOf(baseDN)));
- break searchProcessing;
- }
-
-
- // We'll set the result code to "success". If a problem occurs, then it
- // will be overwritten.
- setResultCode(ResultCode.SUCCESS);
-
-
- // If there's a persistent search, then register it with the server.
- if (persistentSearch != null)
- {
- DirectoryServer.registerPersistentSearch(persistentSearch);
- sendResponse = false;
- }
-
-
- // Process the search in the backend and all its subordinates.
- try
- {
- if (processSearch)
- {
- searchBackend(backend);
- }
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
- }
-
- setResultCode(de.getResultCode());
- appendErrorMessage(de.getErrorMessage());
- setMatchedDN(de.getMatchedDN());
- setReferralURLs(de.getReferralURLs());
-
- if (persistentSearch != null)
- {
- DirectoryServer.deregisterPersistentSearch(persistentSearch);
- sendResponse = true;
- }
-
- break searchProcessing;
- }
- catch (CancelledOperationException coe)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, coe);
- }
-
- CancelResult cancelResult = coe.getCancelResult();
-
- setCancelResult(cancelResult);
- setResultCode(cancelResult.getResultCode());
-
- String message = coe.getMessage();
- if ((message != null) && (message.length() > 0))
- {
- appendErrorMessage(message);
- }
-
- if (persistentSearch != null)
- {
- DirectoryServer.deregisterPersistentSearch(persistentSearch);
- sendResponse = true;
- }
-
- skipPostOperation = true;
- break searchProcessing;
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- setResultCode(DirectoryServer.getServerErrorResultCode());
-
- int msgID = MSGID_SEARCH_BACKEND_EXCEPTION;
- appendErrorMessage(getMessage(msgID, getExceptionMessage(e)));
-
- if (persistentSearch != null)
- {
- DirectoryServer.deregisterPersistentSearch(persistentSearch);
- sendResponse = true;
- }
-
- skipPostOperation = true;
- break searchProcessing;
- }
- }
-
-
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- indicateCancelled(cancelRequest);
- processingStopTime = System.currentTimeMillis();
- logSearchResultDone(this);
- pluginConfigManager.invokePostResponseSearchPlugins(this);
- return;
- }
-
-
- // Invoke the post-operation search plugins.
- if (! skipPostOperation)
- {
- PostOperationPluginResult postOperationResult =
- pluginConfigManager.invokePostOperationSearchPlugins(this);
- if (postOperationResult.connectionTerminated())
- {
- setResultCode(ResultCode.CANCELED);
-
- int msgID = MSGID_CANCELED_BY_POSTOP_DISCONNECT;
- appendErrorMessage(getMessage(msgID));
-
- processingStopTime = System.currentTimeMillis();
- logSearchResultDone(this);
- pluginConfigManager.invokePostResponseSearchPlugins(this);
- return;
- }
- }
-
-
- // Indicate that it is now too late to attempt to cancel the operation.
- setCancelResult(CancelResult.TOO_LATE);
-
-
- // Stop the processing timer.
- processingStopTime = System.currentTimeMillis();
-
-
- // If everything is successful to this point and it is not a persistent
- // search, then send the search result done message to the client.
- // Otherwise, we'll want to make the size and time limit values unlimited
- // to ensure that the remainder of the persistent search isn't subject to
- // those restrictions.
- if (sendResponse)
- {
- sendSearchResultDone();
- }
- else
- {
- sizeLimit = 0;
- timeLimit = 0;
- }
- }
-
-
-
- /**
- * Processes the search in the provided backend and recursively through its
- * subordinate backends.
+ * Set the proxied authorization DN for this operation if proxied
+ * authorization has been requested.
*
- * @param backend The backend in which to process the search.
- *
- * @throws DirectoryException If a problem occurs while processing the
- * search.
- *
- * @throws CancelledOperationException If the backend noticed and reacted
- * to a request to cancel or abandon the
- * search operation.
+ * @param proxiedAuthorizationDN
+ * The proxied authorization DN for this operation if proxied
+ * authorization has been requested, or {@code null} if proxied
+ * authorization has not been requested.
*/
- private final void searchBackend(Backend backend)
- throws DirectoryException, CancelledOperationException
- {
- // Check for and handle a request to cancel this operation.
- if (cancelRequest != null)
- {
- setCancelResult(CancelResult.CANCELED);
- processingStopTime = System.currentTimeMillis();
- return;
- }
+ public abstract void setProxiedAuthorizationDN(DN proxiedAuthorizationDN);
-
- // Perform the search in the provided backend.
- backend.search(this);
-
-
- // If there are any subordinate backends, then process the search there as
- // well.
- Backend[] subBackends = backend.getSubordinateBackends();
- for (Backend b : subBackends)
- {
- DN[] baseDNs = b.getBaseDNs();
- for (DN dn : baseDNs)
- {
- if (dn.isDescendantOf(baseDN))
- {
- searchBackend(b);
- break;
- }
- }
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelResult cancel(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
-
- if (persistentSearch != null)
- {
- DirectoryServer.deregisterPersistentSearch(persistentSearch);
- persistentSearch = null;
- }
-
- CancelResult cancelResult = getCancelResult();
- long stopWaitingTime = System.currentTimeMillis() + 5000;
- while ((cancelResult == null) &&
- (System.currentTimeMillis() < stopWaitingTime))
- {
- try
- {
- Thread.sleep(50);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
-
- cancelResult = getCancelResult();
- }
-
- if (cancelResult == null)
- {
- // This can happen in some rare cases (e.g., if a client disconnects and
- // there is still a lot of data to send to that client), and in this case
- // we'll prevent the cancel thread from blocking for a long period of
- // time.
- cancelResult = CancelResult.CANNOT_CANCEL;
- }
-
- return cancelResult;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final CancelRequest getCancelRequest()
- {
- return cancelRequest;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
- {
- this.cancelRequest = cancelRequest;
- return true;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public final void toString(StringBuilder buffer)
- {
- buffer.append("SearchOperation(connID=");
- buffer.append(clientConnection.getConnectionID());
- buffer.append(", opID=");
- buffer.append(operationID);
- buffer.append(", baseDN=");
- buffer.append(rawBaseDN);
- buffer.append(", scope=");
- buffer.append(scope.toString());
- buffer.append(", filter=");
- buffer.append(rawFilter.toString());
- buffer.append(")");
- }
-}
-
+}
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationBasis.java b/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationBasis.java
new file mode 100644
index 0000000..7710d7c
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationBasis.java
@@ -0,0 +1,1759 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.opends.server.api.ClientConnection;
+import org.opends.server.api.plugin.PreParsePluginResult;
+import org.opends.server.api.plugin.SearchEntryPluginResult;
+import org.opends.server.api.plugin.SearchReferencePluginResult;
+import org.opends.server.controls.AccountUsableResponseControl;
+import org.opends.server.controls.MatchedValuesControl;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.ldap.LDAPFilter;
+import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.FilterType;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.RawFilter;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchResultEntry;
+import org.opends.server.types.SearchResultReference;
+import org.opends.server.types.SearchScope;
+import org.opends.server.types.operation.PostResponseSearchOperation;
+import org.opends.server.types.operation.PreParseSearchOperation;
+import org.opends.server.types.operation.SearchEntrySearchOperation;
+import org.opends.server.types.operation.SearchReferenceSearchOperation;
+import org.opends.server.util.TimeThread;
+
+import static org.opends.server.core.CoreConstants.*;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.AccessLogger.*;
+import static org.opends.server.messages.CoreMessages.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.toLowerCase;
+
+/**
+ * This class defines an operation that may be used to locate entries in the
+ * Directory Server based on a given set of criteria.
+ */
+public class SearchOperationBasis
+ extends AbstractOperation
+ implements PreParseSearchOperation,
+ PostResponseSearchOperation,
+ SearchEntrySearchOperation,
+ SearchReferenceSearchOperation,
+ SearchOperation
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
+
+ // Indicates whether a search result done response has been sent to the
+ // client.
+ private AtomicBoolean responseSent;
+
+ // Indicates whether the client is able to handle referrals.
+ private boolean clientAcceptsReferrals;
+
+ // Indicates whether to include the account usable control with search result
+ // entries.
+ private boolean includeUsableControl;
+
+ // Indicates whether to only real attributes should be returned.
+ private boolean realAttributesOnly;
+
+ // Indicates whether LDAP subentries should be returned.
+ private boolean returnLDAPSubentries;
+
+ // Indicates whether to include attribute types only or both types and values.
+ private boolean typesOnly;
+
+ // Indicates whether to only virtual attributes should be returned.
+ private boolean virtualAttributesOnly;
+
+ // The raw, unprocessed base DN as included in the request from the client.
+ private ByteString rawBaseDN;
+
+ // The cancel request that has been issued for this search operation.
+ private CancelRequest cancelRequest;
+
+ // The dereferencing policy for the search operation.
+ private DereferencePolicy derefPolicy;
+
+ // The base DN for the search operation.
+ private DN baseDN;
+
+ // The proxied authorization target DN for this operation.
+ private DN proxiedAuthorizationDN;
+
+ // The number of entries that have been sent to the client.
+ private int entriesSent;
+
+ // The number of search result references that have been sent to the client.
+ private int referencesSent;
+
+ // The size limit for the search operation.
+ private int sizeLimit;
+
+ // The time limit for the search operation.
+ private int timeLimit;
+
+ // The raw, unprocessed filter as included in the request from the client.
+ private RawFilter rawFilter;
+
+ // The set of attributes that should be returned in matching entries.
+ private LinkedHashSet<String> attributes;
+
+ // The set of response controls for this search operation.
+ private List<Control> responseControls;
+
+ // The time that processing started on this operation.
+ private long processingStartTime;
+
+ // The time that processing ended on this operation.
+ private long processingStopTime;
+
+ // The time that the search time limit has expired.
+ private long timeLimitExpiration;
+
+ // The matched values control associated with this search operation.
+ private MatchedValuesControl matchedValuesControl;
+
+ // The persistent search associated with this search operation.
+ private PersistentSearch persistentSearch;
+
+ // The search filter for the search operation.
+ private SearchFilter filter;
+
+ // The search scope for the search operation.
+ private SearchScope scope;
+
+ // Indicates wether to send the search result done to the client or not
+ private boolean sendResponse = true;
+
+ /**
+ * Creates a new search operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param rawBaseDN The raw, unprocessed base DN as included in the
+ * request from the client.
+ * @param scope The scope for this search operation.
+ * @param derefPolicy The alias dereferencing policy for this search
+ * operation.
+ * @param sizeLimit The size limit for this search operation.
+ * @param timeLimit The time limit for this search operation.
+ * @param typesOnly The typesOnly flag for this search operation.
+ * @param rawFilter the raw, unprocessed filter as included in the
+ * request from the client.
+ * @param attributes The requested attributes for this search
+ * operation.
+ */
+ public SearchOperationBasis(ClientConnection clientConnection,
+ long operationID,
+ int messageID, List<Control> requestControls,
+ ByteString rawBaseDN, SearchScope scope,
+ DereferencePolicy derefPolicy, int sizeLimit,
+ int timeLimit, boolean typesOnly, RawFilter rawFilter,
+ LinkedHashSet<String> attributes)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.rawBaseDN = rawBaseDN;
+ this.scope = scope;
+ this.derefPolicy = derefPolicy;
+ this.sizeLimit = sizeLimit;
+ this.timeLimit = timeLimit;
+ this.typesOnly = typesOnly;
+ this.rawFilter = rawFilter;
+
+ if (attributes == null)
+ {
+ this.attributes = new LinkedHashSet<String>(0);
+ }
+ else
+ {
+ this.attributes = attributes;
+ }
+
+
+ if (clientConnection.getSizeLimit() <= 0)
+ {
+ this.sizeLimit = sizeLimit;
+ }
+ else
+ {
+ if (sizeLimit <= 0)
+ {
+ this.sizeLimit = clientConnection.getSizeLimit();
+ }
+ else
+ {
+ this.sizeLimit = Math.min(sizeLimit, clientConnection.getSizeLimit());
+ }
+ }
+
+
+ if (clientConnection.getTimeLimit() <= 0)
+ {
+ this.timeLimit = timeLimit;
+ }
+ else
+ {
+ if (timeLimit <= 0)
+ {
+ this.timeLimit = clientConnection.getTimeLimit();
+ }
+ else
+ {
+ this.timeLimit = Math.min(timeLimit, clientConnection.getTimeLimit());
+ }
+ }
+
+
+ baseDN = null;
+ filter = null;
+ entriesSent = 0;
+ referencesSent = 0;
+ responseControls = new ArrayList<Control>();
+ cancelRequest = null;
+ clientAcceptsReferrals = true;
+ includeUsableControl = false;
+ responseSent = new AtomicBoolean(false);
+ persistentSearch = null;
+ returnLDAPSubentries = false;
+ matchedValuesControl = null;
+ realAttributesOnly = false;
+ virtualAttributesOnly = false;
+ }
+
+
+
+ /**
+ * Creates a new search operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this operation
+ * is associated.
+ * @param operationID The operation ID for this operation.
+ * @param messageID The message ID of the request with which this
+ * operation is associated.
+ * @param requestControls The set of controls included in the request.
+ * @param baseDN The base DN for this search operation.
+ * @param scope The scope for this search operation.
+ * @param derefPolicy The alias dereferencing policy for this search
+ * operation.
+ * @param sizeLimit The size limit for this search operation.
+ * @param timeLimit The time limit for this search operation.
+ * @param typesOnly The typesOnly flag for this search operation.
+ * @param filter The filter for this search operation.
+ * @param attributes The attributes for this search operation.
+ */
+ public SearchOperationBasis(ClientConnection clientConnection,
+ long operationID,
+ int messageID, List<Control> requestControls,
+ DN baseDN, SearchScope scope,
+ DereferencePolicy derefPolicy, int sizeLimit,
+ int timeLimit, boolean typesOnly, SearchFilter filter,
+ LinkedHashSet<String> attributes)
+ {
+ super(clientConnection, operationID, messageID, requestControls);
+
+
+ this.baseDN = baseDN;
+ this.scope = scope;
+ this.derefPolicy = derefPolicy;
+ this.sizeLimit = sizeLimit;
+ this.timeLimit = timeLimit;
+ this.typesOnly = typesOnly;
+ this.filter = filter;
+
+ if (attributes == null)
+ {
+ this.attributes = new LinkedHashSet<String>(0);
+ }
+ else
+ {
+ this.attributes = attributes;
+ }
+
+ rawBaseDN = new ASN1OctetString(baseDN.toString());
+ rawFilter = new LDAPFilter(filter);
+
+
+ if (clientConnection.getSizeLimit() <= 0)
+ {
+ this.sizeLimit = sizeLimit;
+ }
+ else
+ {
+ if (sizeLimit <= 0)
+ {
+ this.sizeLimit = clientConnection.getSizeLimit();
+ }
+ else
+ {
+ this.sizeLimit = Math.min(sizeLimit, clientConnection.getSizeLimit());
+ }
+ }
+
+
+ if (clientConnection.getTimeLimit() <= 0)
+ {
+ this.timeLimit = timeLimit;
+ }
+ else
+ {
+ if (timeLimit <= 0)
+ {
+ this.timeLimit = clientConnection.getTimeLimit();
+ }
+ else
+ {
+ this.timeLimit = Math.min(timeLimit, clientConnection.getTimeLimit());
+ }
+ }
+
+
+ entriesSent = 0;
+ referencesSent = 0;
+ responseControls = new ArrayList<Control>();
+ cancelRequest = null;
+ clientAcceptsReferrals = true;
+ includeUsableControl = false;
+ responseSent = new AtomicBoolean(false);
+ persistentSearch = null;
+ returnLDAPSubentries = false;
+ matchedValuesControl = null;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ByteString getRawBaseDN()
+ {
+ return rawBaseDN;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawBaseDN(ByteString rawBaseDN)
+ {
+ this.rawBaseDN = rawBaseDN;
+
+ baseDN = null;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getBaseDN()
+ {
+ try
+ {
+ if (baseDN == null)
+ {
+ baseDN = DN.decode(rawBaseDN);
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResultCode(de.getResultCode());
+ appendErrorMessage(de.getErrorMessage());
+ setMatchedDN(de.getMatchedDN());
+ setReferralURLs(de.getReferralURLs());
+ }
+ return baseDN;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setBaseDN(DN baseDN)
+ {
+ this.baseDN = baseDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final SearchScope getScope()
+ {
+ return scope;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setScope(SearchScope scope)
+ {
+ this.scope = scope;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DereferencePolicy getDerefPolicy()
+ {
+ return derefPolicy;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setDerefPolicy(DereferencePolicy derefPolicy)
+ {
+ this.derefPolicy = derefPolicy;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int getSizeLimit()
+ {
+ return sizeLimit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setSizeLimit(int sizeLimit)
+ {
+ this.sizeLimit = sizeLimit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int getTimeLimit()
+ {
+ return timeLimit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setTimeLimit(int timeLimit)
+ {
+ this.timeLimit = timeLimit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final boolean getTypesOnly()
+ {
+ return typesOnly;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setTypesOnly(boolean typesOnly)
+ {
+ this.typesOnly = typesOnly;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final RawFilter getRawFilter()
+ {
+ return rawFilter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setRawFilter(RawFilter rawFilter)
+ {
+ this.rawFilter = rawFilter;
+
+ filter = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final SearchFilter getFilter()
+ {
+ try
+ {
+ if (filter == null)
+ {
+ filter = rawFilter.toSearchFilter();
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResultCode(de.getResultCode());
+ appendErrorMessage(de.getErrorMessage());
+ setMatchedDN(de.getMatchedDN());
+ setReferralURLs(de.getReferralURLs());
+ }
+ return filter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final LinkedHashSet<String> getAttributes()
+ {
+ return attributes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setAttributes(LinkedHashSet<String> attributes)
+ {
+ if (attributes == null)
+ {
+ this.attributes.clear();
+ }
+ else
+ {
+ this.attributes = attributes;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int getEntriesSent()
+ {
+ return entriesSent;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int getReferencesSent()
+ {
+ return referencesSent;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final boolean returnEntry(Entry entry, List<Control> controls)
+ {
+ boolean typesOnly = getTypesOnly();
+ // See if the operation has been abandoned. If so, then don't send the
+ // entry and indicate that the search should end.
+ if (getCancelRequest() != null)
+ {
+ setResultCode(ResultCode.CANCELED);
+ return false;
+ }
+
+ // See if the size limit has been exceeded. If so, then don't send the
+ // entry and indicate that the search should end.
+ if ((getSizeLimit() > 0) && (getEntriesSent() >= getSizeLimit()))
+ {
+ setResultCode(ResultCode.SIZE_LIMIT_EXCEEDED);
+ appendErrorMessage(getMessage(MSGID_SEARCH_SIZE_LIMIT_EXCEEDED,
+ getSizeLimit()));
+ return false;
+ }
+
+ // See if the time limit has expired. If so, then don't send the entry and
+ // indicate that the search should end.
+ if ((getTimeLimit() > 0) && (TimeThread.getTime() >=
+ getTimeLimitExpiration()))
+ {
+ setResultCode(ResultCode.TIME_LIMIT_EXCEEDED);
+ appendErrorMessage(getMessage(MSGID_SEARCH_TIME_LIMIT_EXCEEDED,
+ getTimeLimit()));
+ return false;
+ }
+
+ // Determine whether the provided entry is a subentry and if so whether it
+ // should be returned.
+ if ((getScope() != SearchScope.BASE_OBJECT) &&
+ (! isReturnLDAPSubentries()) &&
+ entry.isLDAPSubentry())
+ {
+ // Check to see if the filter contains an equality element with the
+ // objectclass attribute type and a value of "ldapSubentry". If so, then
+ // we'll return it anyway. Technically, this isn't part of the
+ // specification so we don't need to get carried away with really in-depth
+ // checks.
+ SearchFilter filter = getFilter();
+ switch (filter.getFilterType())
+ {
+ case AND:
+ case OR:
+ for (SearchFilter f : filter.getFilterComponents())
+ {
+ if ((f.getFilterType() == FilterType.EQUALITY) &&
+ (f.getAttributeType().isObjectClassType()))
+ {
+ AttributeValue v = f.getAssertionValue();
+ if (toLowerCase(v.getStringValue()).equals("ldapsubentry"))
+ {
+ setReturnLDAPSubentries(true);
+ }
+ break;
+ }
+ }
+ break;
+ case EQUALITY:
+ AttributeType t = filter.getAttributeType();
+ if (t.isObjectClassType())
+ {
+ AttributeValue v = filter.getAssertionValue();
+ if (toLowerCase(v.getStringValue()).equals("ldapsubentry"))
+ {
+ setReturnLDAPSubentries(true);
+ }
+ }
+ break;
+ }
+
+ if (! isReturnLDAPSubentries())
+ {
+ // We still shouldn't return it even based on the filter. Just throw it
+ // away without doing anything.
+ return true;
+ }
+ }
+
+
+ // Determine whether to include the account usable control. If so, then
+ // create it now.
+ if (isIncludeUsableControl())
+ {
+ try
+ {
+ // FIXME -- Need a way to enable PWP debugging.
+ PasswordPolicyState pwpState = new PasswordPolicyState(entry, false,
+ false);
+
+ boolean isInactive = pwpState.isDisabled() ||
+ pwpState.isAccountExpired();
+ boolean isLocked = pwpState.lockedDueToFailures() ||
+ pwpState.lockedDueToMaximumResetAge() ||
+ pwpState.lockedDueToIdleInterval();
+ boolean isReset = pwpState.mustChangePassword();
+ boolean isExpired = pwpState.isPasswordExpired();
+
+ if (isInactive || isLocked || isReset || isExpired)
+ {
+ int secondsBeforeUnlock = pwpState.getSecondsUntilUnlock();
+ int remainingGraceLogins = pwpState.getGraceLoginsRemaining();
+
+ if (controls == null)
+ {
+ controls = new ArrayList<Control>(1);
+ }
+
+ controls.add(new AccountUsableResponseControl(isInactive, isReset,
+ isExpired, remainingGraceLogins, isLocked,
+ secondsBeforeUnlock));
+ }
+ else
+ {
+ if (controls == null)
+ {
+ controls = new ArrayList<Control>(1);
+ }
+
+ int secondsBeforeExpiration = pwpState.getSecondsUntilExpiration();
+ controls.add(new AccountUsableResponseControl(
+ secondsBeforeExpiration));
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+
+ // Check to see if the entry can be read by the client.
+ SearchResultEntry tmpSearchEntry = new SearchResultEntry(entry,
+ controls);
+ if (AccessControlConfigManager.getInstance()
+ .getAccessControlHandler().maySend(this, tmpSearchEntry) == false) {
+ return true;
+ }
+
+ // Make a copy of the entry and pare it down to only include the set
+ // of
+ // requested attributes.
+ Entry entryToReturn;
+ if ((getAttributes() == null) || getAttributes().isEmpty())
+ {
+ entryToReturn = entry.duplicateWithoutOperationalAttributes(typesOnly,
+ true);
+ }
+ else
+ {
+ entryToReturn = entry.duplicateWithoutAttributes();
+
+ for (String attrName : getAttributes())
+ {
+ if (attrName.equals("*"))
+ {
+ // This is a special placeholder indicating that all user attributes
+ // should be returned.
+ if (typesOnly)
+ {
+ // First, add the placeholder for the objectclass attribute.
+ AttributeType ocType =
+ DirectoryServer.getObjectClassAttributeType();
+ List<Attribute> ocList = new ArrayList<Attribute>(1);
+ ocList.add(new Attribute(ocType));
+ entryToReturn.putAttribute(ocType, ocList);
+ }
+ else
+ {
+ // First, add the objectclass attribute.
+ Attribute ocAttr = entry.getObjectClassAttribute();
+ try
+ {
+ entryToReturn.setObjectClasses(ocAttr.getValues());
+ }
+ catch (DirectoryException e)
+ {
+ // We cannot get this exception because the object classes have
+ // already been validated in the entry they came from.
+ }
+ }
+
+ // Next iterate through all the user attributes and include them.
+ for (AttributeType t : entry.getUserAttributes().keySet())
+ {
+ List<Attribute> attrList =
+ entry.duplicateUserAttribute(t, null, typesOnly);
+ entryToReturn.putAttribute(t, attrList);
+ }
+
+ continue;
+ }
+ else if (attrName.equals("+"))
+ {
+ // This is a special placeholder indicating that all operational
+ // attributes should be returned.
+ for (AttributeType t : entry.getOperationalAttributes().keySet())
+ {
+ List<Attribute> attrList =
+ entry.duplicateOperationalAttribute(t, null, typesOnly);
+ entryToReturn.putAttribute(t, attrList);
+ }
+
+ continue;
+ }
+
+ String lowerName;
+ HashSet<String> options;
+ int semicolonPos = attrName.indexOf(';');
+ if (semicolonPos > 0)
+ {
+ lowerName = toLowerCase(attrName.substring(0, semicolonPos));
+ int nextPos = attrName.indexOf(';', semicolonPos+1);
+ options = new HashSet<String>();
+ while (nextPos > 0)
+ {
+ options.add(attrName.substring(semicolonPos+1, nextPos));
+
+ semicolonPos = nextPos;
+ nextPos = attrName.indexOf(';', semicolonPos+1);
+ }
+
+ options.add(attrName.substring(semicolonPos+1));
+ }
+ else
+ {
+ lowerName = toLowerCase(attrName);
+ options = null;
+ }
+
+
+ AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
+ if (attrType == null)
+ {
+ boolean added = false;
+ for (AttributeType t : entry.getUserAttributes().keySet())
+ {
+ if (t.hasNameOrOID(lowerName))
+ {
+ List<Attribute> attrList =
+ entry.duplicateUserAttribute(t, options, typesOnly);
+ if (attrList != null)
+ {
+ entryToReturn.putAttribute(t, attrList);
+
+ added = true;
+ break;
+ }
+ }
+ }
+
+ if (added)
+ {
+ continue;
+ }
+
+ for (AttributeType t : entry.getOperationalAttributes().keySet())
+ {
+ if (t.hasNameOrOID(lowerName))
+ {
+ List<Attribute> attrList =
+ entry.duplicateOperationalAttribute(t, options, typesOnly);
+ if (attrList != null)
+ {
+ entryToReturn.putAttribute(t, attrList);
+
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (attrType.isObjectClassType()) {
+ if (typesOnly)
+ {
+ AttributeType ocType =
+ DirectoryServer.getObjectClassAttributeType();
+ List<Attribute> ocList = new ArrayList<Attribute>(1);
+ ocList.add(new Attribute(ocType));
+ entryToReturn.putAttribute(ocType, ocList);
+ }
+ else
+ {
+ List<Attribute> attrList = new ArrayList<Attribute>(1);
+ attrList.add(entry.getObjectClassAttribute());
+ entryToReturn.putAttribute(attrType, attrList);
+ }
+ }
+ else
+ {
+ List<Attribute> attrList =
+ entry.duplicateOperationalAttribute(attrType, options,
+ typesOnly);
+ if (attrList == null)
+ {
+ attrList = entry.duplicateUserAttribute(attrType, options,
+ typesOnly);
+ }
+ if (attrList != null)
+ {
+ entryToReturn.putAttribute(attrType, attrList);
+ }
+ }
+ }
+ }
+ }
+
+ if (isRealAttributesOnly())
+ {
+ entryToReturn.stripVirtualAttributes();
+ }
+ else if (isVirtualAttributesOnly())
+ {
+ entryToReturn.stripRealAttributes();
+ }
+
+ // If there is a matched values control, then further pare down the entry
+ // based on the filters that it contains.
+ MatchedValuesControl matchedValuesControl = getMatchedValuesControl();
+ if ((matchedValuesControl != null) && (! typesOnly))
+ {
+ // First, look at the set of objectclasses.
+ AttributeType attrType = DirectoryServer.getObjectClassAttributeType();
+ Iterator<String> ocIterator =
+ entryToReturn.getObjectClasses().values().iterator();
+ while (ocIterator.hasNext())
+ {
+ String ocName = ocIterator.next();
+ AttributeValue v = new AttributeValue(attrType,
+ new ASN1OctetString(ocName));
+ if (! matchedValuesControl.valueMatches(attrType, v))
+ {
+ ocIterator.remove();
+ }
+ }
+
+
+ // Next, the set of user attributes.
+ for (AttributeType t : entryToReturn.getUserAttributes().keySet())
+ {
+ for (Attribute a : entryToReturn.getUserAttribute(t))
+ {
+ Iterator<AttributeValue> valueIterator = a.getValues().iterator();
+ while (valueIterator.hasNext())
+ {
+ AttributeValue v = valueIterator.next();
+ if (! matchedValuesControl.valueMatches(t, v))
+ {
+ valueIterator.remove();
+ }
+ }
+ }
+ }
+
+
+ // Then the set of operational attributes.
+ for (AttributeType t : entryToReturn.getOperationalAttributes().keySet())
+ {
+ for (Attribute a : entryToReturn.getOperationalAttribute(t))
+ {
+ Iterator<AttributeValue> valueIterator = a.getValues().iterator();
+ while (valueIterator.hasNext())
+ {
+ AttributeValue v = valueIterator.next();
+ if (! matchedValuesControl.valueMatches(t, v))
+ {
+ valueIterator.remove();
+ }
+ }
+ }
+ }
+ }
+
+
+ // Convert the provided entry to a search result entry.
+ SearchResultEntry searchEntry = new SearchResultEntry(entryToReturn,
+ controls);
+
+ // Strip out any attributes that the client does not have access to.
+
+ // FIXME: need some way to prevent plugins from adding attributes or
+ // values that the client is not permitted to see.
+ searchEntry = AccessControlConfigManager.getInstance()
+ .getAccessControlHandler().filterEntry(this, searchEntry);
+
+ // Invoke any search entry plugins that may be registered with the server.
+ SearchEntryPluginResult pluginResult =
+ DirectoryServer.getPluginConfigManager().
+ invokeSearchResultEntryPlugins(this, searchEntry);
+ if (pluginResult.connectionTerminated())
+ {
+ // We won't attempt to send this entry, and we won't continue with
+ // any processing. Just update the operation to indicate that it was
+ // cancelled and return false.
+ setResultCode(ResultCode.CANCELED);
+ appendErrorMessage(getMessage(MSGID_CANCELED_BY_SEARCH_ENTRY_DISCONNECT,
+ String.valueOf(entry.getDN())));
+ return false;
+ }
+
+
+ // Send the entry to the client.
+ if (pluginResult.sendEntry())
+ {
+ try
+ {
+ sendSearchEntry(searchEntry);
+ // Log the entry sent to the client.
+ logSearchResultEntry(this, searchEntry);
+
+ incrementEntriesSent();
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResponseData(de);
+ return false;
+ }
+ }
+
+ return pluginResult.continueSearch();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final boolean returnReference(SearchResultReference reference)
+ {
+ // See if the operation has been abandoned. If so, then don't send the
+ // reference and indicate that the search should end.
+ if (getCancelRequest() != null)
+ {
+ setResultCode(ResultCode.CANCELED);
+ return false;
+ }
+
+
+ // See if the time limit has expired. If so, then don't send the entry and
+ // indicate that the search should end.
+ if ((getTimeLimit() > 0) && (TimeThread.getTime() >=
+ getTimeLimitExpiration()))
+ {
+ setResultCode(ResultCode.TIME_LIMIT_EXCEEDED);
+ appendErrorMessage(getMessage(MSGID_SEARCH_TIME_LIMIT_EXCEEDED,
+ getTimeLimit()));
+ return false;
+ }
+
+
+ // See if we know that this client can't handle referrals. If so, then
+ // don't even try to send it.
+ if (! isClientAcceptsReferrals())
+ {
+ return true;
+ }
+
+
+ // See if the client has permission to read this reference.
+ if (AccessControlConfigManager.getInstance()
+ .getAccessControlHandler().maySend(this, reference) == false) {
+ return true;
+ }
+
+
+ // Invoke any search reference plugins that may be registered with the
+ // server.
+ SearchReferencePluginResult pluginResult =
+ DirectoryServer.getPluginConfigManager().
+ invokeSearchResultReferencePlugins(this, reference);
+ if (pluginResult.connectionTerminated())
+ {
+ // We won't attempt to send this entry, and we won't continue with
+ // any processing. Just update the operation to indicate that it was
+ // cancelled and return false.
+ setResultCode(ResultCode.CANCELED);
+ appendErrorMessage(getMessage(MSGID_CANCELED_BY_SEARCH_REF_DISCONNECT,
+ String.valueOf(reference.getReferralURLString())));
+ return false;
+ }
+
+
+ // Send the reference to the client. Note that this could throw an
+ // exception, which would indicate that the associated client can't handle
+ // referrals. If that't the case, then set a flag so we'll know not to try
+ // to send any more.
+ if (pluginResult.sendReference())
+ {
+ try
+ {
+ if (sendSearchReference(reference))
+ {
+ // Log the entry sent to the client.
+ logSearchResultReference(this, reference);
+ incrementReferencesSent();
+
+ // FIXME -- Should the size limit apply here?
+ }
+ else
+ {
+ // We know that the client can't handle referrals, so we won't try to
+ // send it any more.
+ setClientAcceptsReferrals(false);
+ }
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+
+ setResponseData(de);
+ return false;
+ }
+ }
+
+ return pluginResult.continueSearch();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void sendSearchResultDone()
+ {
+ // Send the search result done message to the client. We want to make sure
+ // that this only gets sent once, and it's possible that this could be
+ // multithreaded in the event of a persistent search, so do it safely.
+ if (responseSent.compareAndSet(false, true))
+ {
+ // Send the response to the client.
+ clientConnection.sendResponse(this);
+
+ // Log the search result.
+ logSearchResultDone(this);
+
+
+ // Invoke the post-response search plugins.
+ DirectoryServer.getPluginConfigManager().
+ invokePostResponseSearchPlugins(this);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final OperationType getOperationType()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ return OperationType.SEARCH;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message,
+ int messageID)
+ {
+ // Before calling clientConnection.disconnect, we need to mark this
+ // operation as cancelled so that the attempt to cancel it later won't cause
+ // an unnecessary delay.
+ setCancelResult(CancelResult.CANCELED);
+
+ clientConnection.disconnect(disconnectReason, sendNotification, message,
+ messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final String[][] getRequestLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ String attrs;
+ if ((attributes == null) || attributes.isEmpty())
+ {
+ attrs = null;
+ }
+ else
+ {
+ StringBuilder attrBuffer = new StringBuilder();
+ Iterator<String> iterator = attributes.iterator();
+ attrBuffer.append(iterator.next());
+
+ while (iterator.hasNext())
+ {
+ attrBuffer.append(", ");
+ attrBuffer.append(iterator.next());
+ }
+
+ attrs = attrBuffer.toString();
+ }
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_BASE_DN, String.valueOf(rawBaseDN) },
+ new String[] { LOG_ELEMENT_SCOPE, String.valueOf(scope) },
+ new String[] { LOG_ELEMENT_SIZE_LIMIT, String.valueOf(sizeLimit) },
+ new String[] { LOG_ELEMENT_TIME_LIMIT, String.valueOf(timeLimit) },
+ new String[] { LOG_ELEMENT_FILTER, String.valueOf(rawFilter) },
+ new String[] { LOG_ELEMENT_REQUESTED_ATTRIBUTES, attrs }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final String[][] getResponseLogElements()
+ {
+ // Note that no debugging will be done in this method because it is a likely
+ // candidate for being called by the logging subsystem.
+
+ String resultCode = String.valueOf(getResultCode().getIntValue());
+
+ String errorMessage;
+ StringBuilder errorMessageBuffer = getErrorMessage();
+ if (errorMessageBuffer == null)
+ {
+ errorMessage = null;
+ }
+ else
+ {
+ errorMessage = errorMessageBuffer.toString();
+ }
+
+ String matchedDNStr;
+ DN matchedDN = getMatchedDN();
+ if (matchedDN == null)
+ {
+ matchedDNStr = null;
+ }
+ else
+ {
+ matchedDNStr = matchedDN.toString();
+ }
+
+ String referrals;
+ List<String> referralURLs = getReferralURLs();
+ if ((referralURLs == null) || referralURLs.isEmpty())
+ {
+ referrals = null;
+ }
+ else
+ {
+ StringBuilder buffer = new StringBuilder();
+ Iterator<String> iterator = referralURLs.iterator();
+ buffer.append(iterator.next());
+
+ while (iterator.hasNext())
+ {
+ buffer.append(", ");
+ buffer.append(iterator.next());
+ }
+
+ referrals = buffer.toString();
+ }
+
+ String processingTime =
+ String.valueOf(processingStopTime - processingStartTime);
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
+ new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
+ new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
+ new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
+ new String[] { LOG_ELEMENT_ENTRIES_SENT, String.valueOf(entriesSent) },
+ new String[] { LOG_ELEMENT_REFERENCES_SENT,
+ String.valueOf(referencesSent ) },
+ new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return proxiedAuthorizationDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final List<Control> getResponseControls()
+ {
+ return responseControls;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void addResponseControl(Control control)
+ {
+ responseControls.add(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void removeResponseControl(Control control)
+ {
+ responseControls.remove(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final CancelResult cancel(CancelRequest cancelRequest)
+ {
+ this.cancelRequest = cancelRequest;
+
+ if (persistentSearch != null)
+ {
+ DirectoryServer.deregisterPersistentSearch(persistentSearch);
+ persistentSearch = null;
+ }
+
+ CancelResult cancelResult = getCancelResult();
+ long stopWaitingTime = System.currentTimeMillis() + 5000;
+ while ((cancelResult == null) &&
+ (System.currentTimeMillis() < stopWaitingTime))
+ {
+ try
+ {
+ Thread.sleep(50);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+
+ cancelResult = getCancelResult();
+ }
+
+ if (cancelResult == null)
+ {
+ // This can happen in some rare cases (e.g., if a client disconnects and
+ // there is still a lot of data to send to that client), and in this case
+ // we'll prevent the cancel thread from blocking for a long period of
+ // time.
+ cancelResult = CancelResult.CANNOT_CANCEL;
+ }
+
+ return cancelResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final CancelRequest getCancelRequest()
+ {
+ return cancelRequest;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public
+ boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ this.cancelRequest = cancelRequest;
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public final void toString(StringBuilder buffer)
+ {
+ buffer.append("SearchOperation(connID=");
+ buffer.append(clientConnection.getConnectionID());
+ buffer.append(", opID=");
+ buffer.append(operationID);
+ buffer.append(", baseDN=");
+ buffer.append(rawBaseDN);
+ buffer.append(", scope=");
+ buffer.append(scope.toString());
+ buffer.append(", filter=");
+ buffer.append(rawFilter.toString());
+ buffer.append(")");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setTimeLimitExpiration(Long timeLimitExpiration){
+ this.timeLimitExpiration = timeLimitExpiration;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isReturnLDAPSubentries()
+ {
+ return returnLDAPSubentries;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setReturnLDAPSubentries(boolean returnLDAPSubentries)
+ {
+ this.returnLDAPSubentries = returnLDAPSubentries;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MatchedValuesControl getMatchedValuesControl()
+ {
+ return matchedValuesControl;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMatchedValuesControl(MatchedValuesControl controls)
+ {
+ this.matchedValuesControl = controls;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PersistentSearch getPersistentSearch()
+ {
+ return persistentSearch;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isIncludeUsableControl()
+ {
+ return includeUsableControl;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setIncludeUsableControl(boolean includeUsableControl)
+ {
+ this.includeUsableControl = includeUsableControl;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setPersistentSearch(PersistentSearch psearch)
+ {
+ this.persistentSearch = psearch;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Long getTimeLimitExpiration()
+ {
+ return timeLimitExpiration;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isClientAcceptsReferrals()
+ {
+ return clientAcceptsReferrals;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setClientAcceptsReferrals(boolean clientAcceptReferrals)
+ {
+ this.clientAcceptsReferrals = clientAcceptReferrals;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void incrementEntriesSent()
+ {
+ entriesSent++;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void incrementReferencesSent()
+ {
+ referencesSent++;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSendResponse()
+ {
+ return sendResponse;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSendResponse(boolean sendResponse)
+ {
+ this.sendResponse = sendResponse;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isRealAttributesOnly()
+ {
+ return this.realAttributesOnly;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isVirtualAttributesOnly()
+ {
+ return this.virtualAttributesOnly;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRealAttributesOnly(boolean realAttributesOnly)
+ {
+ this.realAttributesOnly = realAttributesOnly;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setVirtualAttributesOnly(boolean virtualAttributesOnly)
+ {
+ this.virtualAttributesOnly = virtualAttributesOnly;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void sendSearchEntry(SearchResultEntry searchEntry)
+ throws DirectoryException
+ {
+ getClientConnection().sendSearchEntry(this, searchEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean sendSearchReference(SearchResultReference searchReference)
+ throws DirectoryException
+ {
+ return getClientConnection().sendSearchReference(this, searchReference);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN)
+ {
+ this.proxiedAuthorizationDN = proxiedAuthorizationDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void run()
+ {
+ setResultCode(ResultCode.UNDEFINED);
+ setSendResponse(true);
+
+ // Get the plugin config manager that will be used for invoking plugins.
+ PluginConfigManager pluginConfigManager =
+ DirectoryServer.getPluginConfigManager();
+
+
+ // Start the processing timer.
+ setProcessingStartTime();
+ int timeLimit = getTimeLimit();
+ Long timeLimitExpiration;
+ if (timeLimit <= 0)
+ {
+ timeLimitExpiration = Long.MAX_VALUE;
+ }
+ else
+ {
+ // FIXME -- Factor in the user's effective time limit.
+ timeLimitExpiration =
+ getProcessingStartTime() + (1000L * timeLimit);
+ }
+ setTimeLimitExpiration(timeLimitExpiration);
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelRequest() != null)
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ logSearchResultDone(this);
+ return;
+ }
+
+ // Create a labeled block of code that we can break out of if a problem is
+ // detected.
+ searchProcessing:
+ {
+ PreParsePluginResult preParseResult =
+ pluginConfigManager.invokePreParseSearchPlugins(this);
+ if (preParseResult.connectionTerminated())
+ {
+ // There's no point in continuing with anything. Log the request and
+ // result and return.
+ setResultCode(ResultCode.CANCELED);
+
+ int msgID = MSGID_CANCELED_BY_PREPARSE_DISCONNECT;
+ appendErrorMessage(getMessage(msgID));
+
+ setProcessingStopTime();
+
+ logSearchRequest(this);
+ logSearchResultDone(this);
+ pluginConfigManager.invokePostResponseSearchPlugins(this);
+ return;
+ }
+ else if (preParseResult.sendResponseImmediately())
+ {
+ logSearchRequest(this);
+ break searchProcessing;
+ }
+ else if (preParseResult.skipCoreProcessing())
+ {
+ break searchProcessing;
+ }
+
+
+ // Log the search request message.
+ logSearchRequest(this);
+
+
+ // Check for and handle a request to cancel this operation.
+ if (getCancelRequest() != null)
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ logSearchResultDone(this);
+ pluginConfigManager.invokePostResponseSearchPlugins(this);
+ return;
+ }
+
+
+ // Process the search base and filter to convert them from their raw forms
+ // as provided by the client to the forms required for the rest of the
+ // search processing.
+ DN baseDN = getBaseDN();
+ if (baseDN == null){
+ break searchProcessing;
+ }
+
+
+ // Retrieve the network group attached to the client connection
+ // and get a workflow to process the operation.
+ NetworkGroup ng = getClientConnection().getNetworkGroup();
+ Workflow workflow = ng.getWorkflowCandidate(baseDN);
+ if (workflow == null)
+ {
+ // We have found no workflow for the requested base DN, just return
+ // a no such entry result code and stop the processing.
+ updateOperationErrMsgAndResCode();
+ break searchProcessing;
+ }
+ workflow.execute(this);
+ }
+
+ // Check for and handle a request to cancel this operation.
+ if ((getCancelRequest() != null) ||
+ (getCancelResult() == CancelResult.CANCELED))
+ {
+ indicateCancelled(getCancelRequest());
+ setProcessingStopTime();
+ logSearchResultDone(this);
+ pluginConfigManager.invokePostResponseSearchPlugins(this);
+ return;
+ }
+
+ // Indicate that it is now too late to attempt to cancel the operation.
+ setCancelResult(CancelResult.TOO_LATE);
+
+ // Stop the processing timer.
+ setProcessingStopTime();
+
+ // If everything is successful to this point and it is not a persistent
+ // search, then send the search result done message to the client.
+ // Otherwise, we'll want to make the size and time limit values unlimited
+ // to ensure that the remainder of the persistent search isn't subject to
+ // those restrictions.
+ if (isSendResponse())
+ {
+ sendSearchResultDone();
+ }
+ else
+ {
+ setSizeLimit(0);
+ setTimeLimit(0);
+ }
+ }
+
+ /**
+ * Updates the error message and the result code of the operation.
+ *
+ * This method is called because no workflows were found to process
+ * the operation.
+ */
+ private void updateOperationErrMsgAndResCode()
+ {
+ setResultCode(ResultCode.NO_SUCH_OBJECT);
+ appendErrorMessage(getMessage(MSGID_SEARCH_BASE_DOESNT_EXIST,
+ String.valueOf(getBaseDN())));
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationWrapper.java b/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationWrapper.java
new file mode 100644
index 0000000..415da2e
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationWrapper.java
@@ -0,0 +1,903 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.opends.server.api.ClientConnection;
+import org.opends.server.controls.MatchedValuesControl;
+import org.opends.server.types.ByteString;
+import org.opends.server.types.CancelRequest;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.RawFilter;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchResultEntry;
+import org.opends.server.types.SearchResultReference;
+import org.opends.server.types.SearchScope;
+
+/**
+ * This abstract class wraps/decorates a given search operation.
+ * This class will be extended by sub-classes to enhance the
+ * functionnality of the SearchOperationBasis.
+ */
+public abstract class SearchOperationWrapper implements SearchOperation
+{
+ private SearchOperation search;
+
+ /**
+ * Creates a new search operation based on the provided search operation.
+ *
+ * @param search The search operation to wrap
+ */
+ protected SearchOperationWrapper(SearchOperation search){
+ this.search = search;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addRequestControl(Control control)
+ {
+ search.addRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addResponseControl(Control control)
+ {
+ search.addResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendAdditionalLogMessage(String message)
+ {
+ search.appendAdditionalLogMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void appendErrorMessage(String message)
+ {
+ search.appendErrorMessage(message);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult cancel(CancelRequest cancelRequest)
+ {
+ return search.cancel(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void disconnectClient(DisconnectReason disconnectReason,
+ boolean sendNotification, String message, int messageID)
+ {
+ search.disconnectClient(disconnectReason, sendNotification, message,
+ messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean dontSynchronize()
+ {
+ return search.dontSynchronize();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getAdditionalLogMessage()
+ {
+ return search.getAdditionalLogMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getAttachment(String name)
+ {
+ return search.getAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<String, Object> getAttachments()
+ {
+ return search.getAttachments();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getAuthorizationDN()
+ {
+ return search.getAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry getAuthorizationEntry()
+ {
+ return search.getAuthorizationEntry();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelRequest getCancelRequest()
+ {
+ return search.getCancelRequest();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CancelResult getCancelResult()
+ {
+ return search.getCancelResult();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClientConnection getClientConnection()
+ {
+ return search.getClientConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getCommonLogElements()
+ {
+ return search.getCommonLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getConnectionID()
+ {
+ return search.getConnectionID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public StringBuilder getErrorMessage()
+ {
+ return search.getErrorMessage();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getMatchedDN()
+ {
+ return search.getMatchedDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMessageID()
+ {
+ return search.getMessageID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getOperationID()
+ {
+ return search.getOperationID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public OperationType getOperationType()
+ {
+ return search.getOperationType();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStartTime()
+ {
+ return search.getProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingStopTime()
+ {
+ return search.getProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getProcessingTime()
+ {
+ return search.getProcessingTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<String> getReferralURLs()
+ {
+ return search.getReferralURLs();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getRequestControls()
+ {
+ return search.getRequestControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getRequestLogElements()
+ {
+ return search.getRequestLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Control> getResponseControls()
+ {
+ return search.getResponseControls();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[][] getResponseLogElements()
+ {
+ return search.getResponseLogElements();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultCode getResultCode()
+ {
+ return search.getResultCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void indicateCancelled(CancelRequest cancelRequest)
+ {
+ search.indicateCancelled(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isInternalOperation()
+ {
+ return search.isInternalOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSynchronizationOperation()
+ {
+ return search.isSynchronizationOperation();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void operationCompleted()
+ {
+ search.operationCompleted();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object removeAttachment(String name)
+ {
+ return search.removeAttachment(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeRequestControl(Control control)
+ {
+ search.removeRequestControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeResponseControl(Control control)
+ {
+ search.removeResponseControl(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean returnEntry(Entry entry, List<Control> controls)
+ {
+ return search.returnEntry(entry, controls);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean returnReference(SearchResultReference reference)
+ {
+ return search.returnReference(reference);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAdditionalLogMessage(StringBuilder additionalLogMessage)
+ {
+ search.setAdditionalLogMessage(additionalLogMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object setAttachment(String name, Object value)
+ {
+ return search.setAttachment(name, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttachments(Map<String, Object> attachments)
+ {
+ search.setAttachments(attachments);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAuthorizationEntry(Entry authorizationEntry)
+ {
+ search.setAuthorizationEntry(authorizationEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean setCancelRequest(CancelRequest cancelRequest)
+ {
+ return search.setCancelRequest(cancelRequest);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCancelResult(CancelResult cancelResult)
+ {
+ search.setCancelResult(cancelResult);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDontSynchronize(boolean dontSynchronize)
+ {
+ search.setDontSynchronize(dontSynchronize);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setErrorMessage(StringBuilder errorMessage)
+ {
+ search.setErrorMessage(errorMessage);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInternalOperation(boolean isInternalOperation)
+ {
+ search.setInternalOperation(isInternalOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMatchedDN(DN matchedDN)
+ {
+ search.setMatchedDN(matchedDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStartTime()
+ {
+ search.setProcessingStartTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProcessingStopTime()
+ {
+ search.setProcessingStopTime();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setReferralURLs(List<String> referralURLs)
+ {
+ search.setReferralURLs(referralURLs);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResponseData(DirectoryException directoryException)
+ {
+ search.setResponseData(directoryException);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setResultCode(ResultCode resultCode)
+ {
+ search.setResultCode(resultCode);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSynchronizationOperation(boolean isSynchronizationOperation)
+ {
+ search.setSynchronizationOperation(isSynchronizationOperation);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString()
+ {
+ return search.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void toString(StringBuilder buffer)
+ {
+ search.toString(buffer);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public LinkedHashSet<String> getAttributes()
+ {
+ return search.getAttributes();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getBaseDN()
+ {
+ return search.getBaseDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DereferencePolicy getDerefPolicy()
+ {
+ return search.getDerefPolicy();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getEntriesSent()
+ {
+ return search.getEntriesSent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SearchFilter getFilter()
+ {
+ return search.getFilter();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString getRawBaseDN()
+ {
+ return search.getRawBaseDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public RawFilter getRawFilter()
+ {
+ return search.getRawFilter();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getReferencesSent()
+ {
+ return search.getReferencesSent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SearchScope getScope()
+ {
+ return search.getScope();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getSizeLimit()
+ {
+ return search.getSizeLimit();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getTimeLimit()
+ {
+ return search.getTimeLimit();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean getTypesOnly()
+ {
+ return search.getTypesOnly();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void sendSearchResultDone()
+ {
+ search.sendSearchResultDone();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAttributes(LinkedHashSet<String> attributes)
+ {
+ search.setAttributes(attributes);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setBaseDN(DN baseDN)
+ {
+ search.setBaseDN(baseDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setDerefPolicy(DereferencePolicy derefPolicy)
+ {
+ search.setDerefPolicy(derefPolicy);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawBaseDN(ByteString rawBaseDN)
+ {
+ search.setRawBaseDN(rawBaseDN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRawFilter(RawFilter rawFilter)
+ {
+ search.setRawFilter(rawFilter);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setScope(SearchScope scope)
+ {
+ search.setScope(scope);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSizeLimit(int sizeLimit)
+ {
+ search.setSizeLimit(sizeLimit);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setTimeLimit(int timeLimit)
+ {
+ search.setTimeLimit(timeLimit);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setTypesOnly(boolean typesOnly)
+ {
+ search.setTypesOnly(typesOnly);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setTimeLimitExpiration(Long timeLimitExpiration)
+ {
+ search.setTimeLimitExpiration(timeLimitExpiration);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isReturnLDAPSubentries()
+ {
+ return search.isReturnLDAPSubentries();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setReturnLDAPSubentries(boolean returnLDAPSubentries)
+ {
+ search.setReturnLDAPSubentries(returnLDAPSubentries);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MatchedValuesControl getMatchedValuesControl()
+ {
+ return search.getMatchedValuesControl();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMatchedValuesControl(MatchedValuesControl controls)
+ {
+ search.setMatchedValuesControl(controls);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isIncludeUsableControl()
+ {
+ return search.isIncludeUsableControl();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setIncludeUsableControl(boolean includeUsableControl)
+ {
+ search.setIncludeUsableControl(includeUsableControl);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setPersistentSearch(PersistentSearch psearch)
+ {
+ search.setPersistentSearch(psearch);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PersistentSearch getPersistentSearch()
+ {
+ return search.getPersistentSearch();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Long getTimeLimitExpiration()
+ {
+ return search.getTimeLimitExpiration();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isClientAcceptsReferrals()
+ {
+ return search.isClientAcceptsReferrals();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setClientAcceptsReferrals(boolean clientAcceptReferrals)
+ {
+ search.setClientAcceptsReferrals(clientAcceptReferrals);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void incrementEntriesSent()
+ {
+ search.incrementEntriesSent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void incrementReferencesSent()
+ {
+ search.incrementReferencesSent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isSendResponse()
+ {
+ return search.isSendResponse();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setSendResponse(boolean sendResponse)
+ {
+ search.setSendResponse(sendResponse);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isRealAttributesOnly(){
+ return search.isRealAttributesOnly();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRealAttributesOnly(boolean realAttributesOnly){
+ search.setRealAttributesOnly(realAttributesOnly);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isVirtualAttributesOnly(){
+ return search.isVirtualAttributesOnly();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setVirtualAttributesOnly(boolean virtualAttributesOnly){
+ search.setVirtualAttributesOnly(virtualAttributesOnly);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws DirectoryException
+ */
+ public void sendSearchEntry(SearchResultEntry entry)
+ throws DirectoryException
+ {
+ search.sendSearchEntry(entry);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws DirectoryException
+ */
+ public boolean sendSearchReference(SearchResultReference reference)
+ throws DirectoryException
+ {
+ return search.sendSearchReference(reference);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN getProxiedAuthorizationDN()
+ {
+ return search.getProxiedAuthorizationDN();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN){
+ search.setProxiedAuthorizationDN(proxiedAuthorizationDN);
+ }
+
+}
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/UnbindOperation.java b/opendj-sdk/opends/src/server/org/opends/server/core/UnbindOperation.java
index 03b920a..44363ac 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/UnbindOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/UnbindOperation.java
@@ -32,11 +32,13 @@
import java.util.List;
import org.opends.server.api.ClientConnection;
+import org.opends.server.loggers.debug.DebugLogger;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.Control;
import org.opends.server.types.DisconnectReason;
-import org.opends.server.types.Operation;
import org.opends.server.types.OperationType;
import org.opends.server.types.operation.PostOperationUnbindOperation;
import org.opends.server.types.operation.PreParseUnbindOperation;
@@ -52,19 +54,14 @@
* between the client and the Directory Server.
*/
public class UnbindOperation
- extends Operation
+ extends AbstractOperation
implements PreParseUnbindOperation, PostOperationUnbindOperation
{
-
-
- // The time that processing started on this operation.
- private long processingStartTime;
-
- // The time that processing ended on this operation.
- private long processingStopTime;
-
-
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = DebugLogger.getTracer();
/**
* Creates a new unbind operation with the provided information.
@@ -180,45 +177,13 @@
// An unbind operation can never have a response, so just ignore this.
}
-
-
/**
- * {@inheritDoc}
+ * Performs the work of actually processing this operation. This
+ * should include all processing for the operation, including
+ * invoking plugins, logging messages, performing access control,
+ * managing synchronization, and any other work that might need to
+ * be done in the course of processing.
*/
- @Override()
- public long getProcessingStartTime()
- {
- return processingStartTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public long getProcessingStopTime()
- {
- return processingStopTime;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
- public long getProcessingTime()
- {
- return (processingStopTime - processingStartTime);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override()
public final void run()
{
// Get the plugin config manager that will be used for invoking plugins.
@@ -226,7 +191,7 @@
DirectoryServer.getPluginConfigManager();
boolean skipPostOperation = false;
- processingStartTime = System.currentTimeMillis();
+ setProcessingStartTime();
// Invoke the pre-parse unbind plugins. We don't care about the result
@@ -250,7 +215,7 @@
// Invoke the post-operation unbind plugins.
pluginConfigManager.invokePostOperationUnbindPlugins(this);
- processingStopTime = System.currentTimeMillis();
+ setProcessingStopTime();
}
@@ -282,7 +247,7 @@
* {@inheritDoc}
*/
@Override()
- protected boolean setCancelRequest(CancelRequest cancelRequest)
+ public boolean setCancelRequest(CancelRequest cancelRequest)
{
// Unbind operations cannot be canceled.
return false;
@@ -302,5 +267,6 @@
buffer.append(operationID);
buffer.append(")");
}
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/Workflow.java b/opendj-sdk/opends/src/server/org/opends/server/core/Workflow.java
new file mode 100644
index 0000000..baad2ba
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/Workflow.java
@@ -0,0 +1,73 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import org.opends.server.types.DN;
+import org.opends.server.types.Operation;
+
+
+/**
+ * This class defines the workflow interface. There can be two
+ * implementations for the workflows.
+ *
+ * In the first workflow implementation a workflow is a list of
+ * structured tasks (aka workflow element). Each task is working
+ * on a set of data being identified by a base DN. The order of the
+ * tasks and their synchronization are defined statically by a task
+ * tree.
+ *
+ * In the second workflow implementation each workflow is a node
+ * in a workflow tree (aka worflow topology). Each node in the tree
+ * is linked to a workflow object of the first implementation and the
+ * base DN of the node is the base DN of the attached workflow object.
+ * The relationship of the nodes in the tree is based on the base DNs
+ * of the nodes. A workflow node is a subordinate of another workflow
+ * node when the base DN of the former is a superior of the base DN of
+ * the latter. Workflow topology are useful, for example, in subtree
+ * searches: search is performed on a node as well as on all the
+ * subordinate nodes.
+ */
+public interface Workflow
+{
+ /**
+ * Gets the base DN which identifies the set of data upon which the
+ * workflow is to be executed.
+ *
+ * @return the base DN of the workflow
+ */
+ public DN getBaseDN();
+
+
+ /**
+ * Executes all the tasks defined by the workflow task tree for a given
+ * operation.
+ *
+ * @param operation the operation to execute
+ */
+ public void execute(Operation operation);
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowImpl.java b/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowImpl.java
new file mode 100644
index 0000000..e811757
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowImpl.java
@@ -0,0 +1,127 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import org.opends.server.types.DN;
+import org.opends.server.types.Operation;
+import org.opends.server.workflowelement.WorkflowElement;
+
+
+/**
+ * This class implements the workflow interface. Each task in the workflow
+ * is implemented by a WorkflowElement. All the tasks in the workflow are
+ * structured in a tree of tasks and the root node of the task tree is
+ * stored in the Workflow class itself. To execute a workflow, one just need
+ * to call the execute method on the root node of the task tree. Then each
+ * task in turn will execute its subordinate nodes and synchronizes them
+ * as needed.
+ */
+public class WorkflowImpl implements Workflow
+{
+
+ // The root of the workflow task tree.
+ private WorkflowElement rootWorkflowElement = null;
+
+ // The base DN of the data handled by the workflow.
+ private DN baseDN = null;
+
+ // Flag indicating whether the workflow root node of the task tree is
+ // handling a private local backend.
+ //
+ // A private local backend is used by the server to store "private data"
+ // such as schemas, tasks, monitoring data, configuration data... Such
+ // private data are not returned upon a subtree search on the root DSE.
+ // Also it is not planned to have anything but a single node task tree
+ // to handle private local backend. So workflows used for proxy and
+ // virtual will always be made public (ie. not private). So, unless the
+ // rootWorkflowElement is handling a private local backend, the isPrivate
+ // flag will always return false.
+ private boolean isPrivate = false;
+
+
+ /**
+ * Creates a new instance of a workflow implementation. To define a worfklow
+ * one needs to provide a task tree root node (the rootWorkflowElement) and
+ * a base DN to identify the data set upon which the tasks can be applied.
+ *
+ * The rootWorkflowElement must not be null.
+ *
+ * @param baseDN identifies the data handled by the workflow
+ * @param rootWorkflowElement the root node of the workflow task tree
+ */
+ public WorkflowImpl(
+ DN baseDN,
+ WorkflowElement rootWorkflowElement
+ )
+ {
+ this.baseDN = baseDN;
+ this.rootWorkflowElement = rootWorkflowElement;
+ if (this.rootWorkflowElement != null)
+ {
+ this.isPrivate = rootWorkflowElement.isPrivate();
+ }
+ }
+
+
+ /**
+ * Gets the base DN of the data set being handled by the workflow.
+ *
+ * @return the workflow base DN
+ */
+ public DN getBaseDN()
+ {
+ return baseDN;
+ }
+
+
+ /**
+ * Indicates whether the root node of the workflow task tree is
+ * handling a private local backend.
+ *
+ * @return <code>true</code> if the workflow encapsulates a private local
+ * backend
+ */
+ public boolean isPrivate()
+ {
+ return isPrivate;
+ }
+
+
+ /**
+ * Executes all the tasks defined by the workflow task tree for a given
+ * operation.
+ *
+ * @param operation the operation to execute
+ */
+ public void execute(
+ Operation operation
+ )
+ {
+ rootWorkflowElement.execute(operation);
+ }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowResultCode.java b/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowResultCode.java
new file mode 100644
index 0000000..28746ae
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowResultCode.java
@@ -0,0 +1,249 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import org.opends.server.types.ResultCode;
+
+
+/**
+ * This class implements the workflow result code. The workflow result code
+ * contains an LDAP result code along with an LDAP error message.
+ */
+public class WorkflowResultCode
+{
+ // The global result code.
+ private ResultCode resultCode = ResultCode.UNDEFINED;
+
+ // The global error message.
+ private StringBuilder errorMessage = new StringBuilder ("");
+
+
+ /**
+ * Creates a new instance of a workflow result. By default the result code
+ * is set to UNDEFINED and there is no error message.
+ */
+ public WorkflowResultCode()
+ {
+ // Nothing to implement.
+ }
+
+
+ /**
+ * Creates a new instance of a workflow result code and initializes it
+ * with a result code and an error message.
+ *
+ * @param resultCode the initial value for the result code
+ * @param errorMessage the initial value for the error message
+ */
+ public WorkflowResultCode(
+ ResultCode resultCode,
+ StringBuilder errorMessage
+ )
+ {
+ this.resultCode = resultCode;
+ this.errorMessage = errorMessage;
+ }
+
+
+ /**
+ * Elaborates a global result code. A workflow may execute an operation
+ * on several subordinate workflows. In such case, the parent workflow
+ * has to take into account all the subordinate result codes to elaborate
+ * a global result code.
+ *
+ * Sometimes, a referral result code has to be turned into a reference
+ * entry. When such case is occurring the elaborateGlobalResultCode method
+ * will return true.
+ *
+ * The global result code is elaborated as follows:
+ *
+ * <PRE>
+ * -----------+------------+------------+-------------------------------
+ * new | current | resulting |
+ * resultCode | resultCode | resultCode | action
+ * -----------+------------+------------+-------------------------------
+ * SUCCESS NO_SUCH_OBJ SUCCESS -
+ * REFERRAL SUCCESS send reference entry to client
+ * other [unchanged] -
+ * ---------------------------------------------------------------------
+ * NO_SUCH_OBJ SUCCESS [unchanged] -
+ * REFERRAL [unchanged] -
+ * other [unchanged] -
+ * ---------------------------------------------------------------------
+ * REFERRAL SUCCESS [unchanged] send reference entry to client
+ * REFERRAL SUCCESS send reference entry to client
+ * NO_SUCH_OBJ REFERRAL -
+ * other [unchanged] send reference entry to client
+ * ---------------------------------------------------------------------
+ * others SUCCESS other -
+ * REFERRAL other send reference entry to client
+ * NO_SUCH_OBJ other -
+ * other2 [unchanged] -
+ * ---------------------------------------------------------------------
+ * </PRE>
+ *
+ * @param newResultCode the new result code to take into account
+ * @param newErrorMessage the new error message associated to the new
+ * error code
+ * @return <code>true</code> if a referral result code must be turned
+ * into a reference entry
+ */
+ public boolean elaborateGlobalResultCode(
+ ResultCode newResultCode,
+ StringBuilder newErrorMessage
+ )
+ {
+ // Returned value
+ boolean sendReferenceEntry = false;
+
+ // if global result code has not been set yet then just take the new
+ // result code as is
+ if (resultCode == ResultCode.UNDEFINED)
+ {
+ resultCode = newResultCode;
+ errorMessage = new StringBuilder (newErrorMessage);
+ }
+ else
+ {
+ // Elaborate the new result code (see table in the description header).
+
+ switch (newResultCode)
+ {
+ case SUCCESS:
+ //
+ // Received SUCCESS
+ // ----------------
+ //
+ switch (resultCode)
+ {
+ case NO_SUCH_OBJECT:
+ resultCode = ResultCode.SUCCESS;
+ errorMessage = new StringBuilder ("");
+ break;
+ case REFERRAL:
+ resultCode = ResultCode.SUCCESS;
+ errorMessage = new StringBuilder ("");
+ sendReferenceEntry = true;
+ break;
+ default:
+ // global resultCode remains the same
+ break;
+ }
+ break;
+ case NO_SUCH_OBJECT:
+ //
+ // Received NO SUCH OBJECT
+ // -----------------------
+ //
+ // global resultCode remains the same
+ break;
+ case REFERRAL:
+ //
+ // Received REFERRAL
+ // -----------------
+ //
+ switch (resultCode)
+ {
+ case REFERRAL:
+ resultCode = ResultCode.SUCCESS;
+ errorMessage = new StringBuilder ("");
+ sendReferenceEntry = true;
+ break;
+ case NO_SUCH_OBJECT:
+ resultCode = ResultCode.REFERRAL;
+ errorMessage = new StringBuilder (newErrorMessage);
+ break;
+ default:
+ // global resultCode remains the same
+ sendReferenceEntry = true;
+ break;
+ }
+ break;
+ default:
+ //
+ // Received other result codes
+ // ---------------------------
+ //
+ switch (resultCode)
+ {
+ case REFERRAL:
+ resultCode = newResultCode;
+ errorMessage = new StringBuilder (newErrorMessage);
+ sendReferenceEntry = true;
+ break;
+ case SUCCESS:
+ resultCode = newResultCode;
+ errorMessage = new StringBuilder (newErrorMessage);
+ break;
+ case NO_SUCH_OBJECT:
+ resultCode = newResultCode;
+ errorMessage = new StringBuilder (newErrorMessage);
+ break;
+ default:
+ // global resultCode remains the same but append the new
+ // error message into the current error message
+ if (errorMessage == null)
+ {
+ errorMessage = new StringBuilder (newErrorMessage);
+ }
+ else
+ {
+ errorMessage.append(newErrorMessage);
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ return sendReferenceEntry;
+ }
+
+
+ /**
+ * Returns the global result code.
+ *
+ * @return the global result code.
+ */
+ public ResultCode resultCode()
+ {
+ return resultCode;
+ }
+
+
+ /**
+ * Returns the global error message.
+ *
+ * @return the global error message.
+ */
+ public StringBuilder errorMessage()
+ {
+ return errorMessage;
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowTopology.java b/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowTopology.java
new file mode 100644
index 0000000..a7543ec
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowTopology.java
@@ -0,0 +1,135 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import org.opends.server.types.DN;
+import org.opends.server.types.SearchScope;
+
+
+/**
+ * This class is the base class used to build the workflow topology.
+ * A workflow topology is a tree of workflows. Each node in the tree
+ * is attached to a WorkflowImpl which contains the task tree (ie. the
+ * processing).
+ *
+ * There are two types of workflow nodes. The first one is used to build
+ * nodes in the workflow topology (WorkflowTopologyNode) and the second
+ * one is used to implement the root DSE node (RootDseWorkflowTopology).
+ */
+
+public abstract class WorkflowTopology implements Workflow
+{
+ // The workflow implementation containing the task tree (ie. the processing)
+ private WorkflowImpl workflowImpl = null;
+
+
+ /**
+ * Each workflow node may have specific tasks to be executed before
+ * the workflow task tree. The tasks to execute before are stored in
+ * the following array, which is empty at the moment (implementation
+ * will come later on when needed).
+ */
+ // private WorkflowElement[] preWorkflowElements = null;
+
+
+ /**
+ * Each workflow node may have specific tasks to be executed after
+ * the workflow task tree. The tasks to execute after are stored in
+ * the following array, which is empty at the moment (implementation
+ * will come later on when needed).
+ */
+ // private WorkflowElement[] postWorkflowElements = null;
+
+
+ /**
+ * Create a new instance of the workflow topology base class.
+ * The instance is initialized with the workflow implementation which
+ * contains the task tree (ie. the processing).
+ *
+ * @param workflowImpl the workflow which contains the processing
+ */
+ protected WorkflowTopology(WorkflowImpl workflowImpl)
+ {
+ this.workflowImpl = workflowImpl;
+ }
+
+
+ /**
+ * Returns the workflow implementation which contains the task tree
+ * (ie. the processing).
+ *
+ * @return the workflow implementation which contains the processing
+ */
+ public WorkflowImpl getWorkflowImpl()
+ {
+ return workflowImpl;
+ }
+
+
+ /**
+ * Gets the base DN of the workflow node. The base DN of the workflow
+ * node is the base DN of the attached workflow implementation containing
+ * the processing.
+ *
+ * @return the base DN of the workflow containing the processing.
+ */
+ public DN getBaseDN()
+ {
+ return getWorkflowImpl().getBaseDN();
+ }
+
+
+ /**
+ * Elaborates a new search scope according to the current search scope.
+ * The new scope is intended to be used for searches on subordinate
+ * workflows.
+ *
+ * @param currentScope the current search scope
+ * @return the new scope to use for searches on subordinate workflows,
+ * <code>null</code> when current scope is 'base'
+ */
+
+ protected SearchScope elaborateScopeForSearchInSubordinates(
+ SearchScope currentScope
+ )
+ {
+ switch (currentScope)
+ {
+ case BASE_OBJECT:
+ return null;
+ case SINGLE_LEVEL:
+ return SearchScope.BASE_OBJECT;
+ case SUBORDINATE_SUBTREE:
+ case WHOLE_SUBTREE:
+ return SearchScope.WHOLE_SUBTREE;
+ default:
+ return currentScope;
+ }
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowTopologyNode.java b/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowTopologyNode.java
new file mode 100644
index 0000000..cc93f7a
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/WorkflowTopologyNode.java
@@ -0,0 +1,535 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import java.util.ArrayList;
+
+import org.opends.server.types.DN;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.SearchScope;
+import org.opends.server.workflowelement.WorkflowElement;
+
+
+/**
+ * This class implements a workflow node. A workflow node is used
+ * to build a tree of workflows (aka workflow topology). Each node
+ * may have a parent node and/or subordinate nodes. A node with no
+ * parent is a naming context.
+ *
+ * Each node in the workflow topology is linked to a WorkflowImpl
+ * which contains the real processing. The base DN of the workflow
+ * node is the base DN of the related WorkflowImpl.
+ *
+ * How the workflow topology is built?
+ * A workflow node is a subordinate of another workflow node when
+ * the base DN of the former workflow is an ancestor of the base DN
+ * of the latter workflow.
+ *
+ * A subtree search on a workflow node is performed on the node itself as
+ * well as on all the subordinate nodes.
+ */
+public class WorkflowTopologyNode extends WorkflowTopology
+{
+ // Parent node of the current workflow node.
+ private WorkflowTopologyNode parent = null;
+
+
+ // The list of subordinate nodes of the current workflow node.
+ private ArrayList<WorkflowTopologyNode> subordinates =
+ new ArrayList<WorkflowTopologyNode>();
+
+
+ /**
+ * Creates a new node for a workflow topology. The new node is initialized
+ * with a WorkflowImpl which contains the real processing. Optionally,
+ * the node may have tasks to be executed before and/or after the real
+ * processing. In the current implementation, such pre and post workflow
+ * elements are not used.
+ *
+ * @param workflowImpl the real processing attached to the node
+ * @param preWorkflowElements the list of tasks to be executed before
+ * the real processing
+ * @param postWorkflowElements the list of tasks to be executed after
+ * the real processing
+ */
+ public WorkflowTopologyNode(
+ WorkflowImpl workflowImpl,
+ WorkflowElement[] preWorkflowElements,
+ WorkflowElement[] postWorkflowElements
+ )
+ {
+ super(workflowImpl);
+ }
+
+
+ /**
+ * Executes an operation on a set of data being identified by the
+ * workflow node base DN.
+ *
+ * @param operation the operation to execute
+ */
+ public void execute(
+ Operation operation
+ )
+ {
+ // Execute the operation
+ getWorkflowImpl().execute(operation);
+
+ // For subtree search operation we need to go through the subordinate
+ // nodes.
+ if (operation.getOperationType() == OperationType.SEARCH)
+ {
+ executeSearchOnSubordinates((SearchOperation) operation);
+ }
+ }
+
+
+ /**
+ * Executes a search operation on the subordinate workflows.
+ *
+ * @param searchOp the search operation to execute
+ */
+ private void executeSearchOnSubordinates(
+ SearchOperation searchOp
+ )
+ {
+ // If the scope of the search is 'base' then it's useless to search
+ // in the subordinate workflows.
+ SearchScope originalScope = searchOp.getScope();
+ if (originalScope == SearchScope.BASE_OBJECT)
+ {
+ return;
+ }
+
+ // Elaborate the new search scope before executing the search operation
+ // in the subordinate workflows.
+ SearchScope newScope = elaborateScopeForSearchInSubordinates(originalScope);
+ searchOp.setScope(newScope);
+
+ // Let's search in the subordinate workflows.
+ WorkflowResultCode workflowResultCode = new WorkflowResultCode(
+ searchOp.getResultCode(), searchOp.getErrorMessage());
+ DN originalBaseDN = searchOp.getBaseDN();
+ for (WorkflowTopologyNode subordinate: getSubordinates())
+ {
+ // We have to change the operation request base DN to match the
+ // subordinate workflow base DN. Otherwise the workflow will
+ // return a no such entry result code as the operation request
+ // base DN is a superior of the subordinate workflow base DN.
+ DN subordinateDN = subordinate.getBaseDN();
+
+ // If the new search scope is 'base' and the search base DN does not
+ // map the subordinate workflow then skip the subordinate workflow.
+ if ((newScope == SearchScope.BASE_OBJECT)
+ && !subordinateDN.getParent().equals(originalBaseDN))
+ {
+ continue;
+ }
+
+ // If the request base DN is not a subordinate of the subordinate
+ // worklfow base DN then don't search in the subordinate workflow.
+ if (! originalBaseDN.isAncestorOf(subordinateDN))
+ {
+ continue;
+ }
+
+ // Set the new request base DN and do execute the
+ // operation in the subordinate workflow.
+ searchOp.setBaseDN(subordinateDN);
+ subordinate.execute(searchOp);
+ boolean sendReferenceEntry =
+ workflowResultCode.elaborateGlobalResultCode(
+ searchOp.getResultCode(), searchOp.getErrorMessage());
+ if (sendReferenceEntry)
+ {
+ // TODO jdemendi - turn a referral result code into a reference entry
+ // and send the reference entry to the client application
+ }
+ }
+
+ // Now we are done with the operation, let's restore the original
+ // base DN and search scope in the operation.
+ searchOp.setBaseDN(originalBaseDN);
+ searchOp.setScope(originalScope);
+
+ // Update the operation result code and error message
+ searchOp.setResultCode(workflowResultCode.resultCode());
+ searchOp.setErrorMessage(workflowResultCode.errorMessage());
+ }
+
+
+ /**
+ * Sets the parent workflow.
+ *
+ * @param parent the parent workflow of the current workflow
+ */
+ public void setParent(WorkflowTopologyNode parent)
+ {
+ this.parent = parent;
+ }
+
+
+ /**
+ * Gets the parent workflow.
+ *
+ * @return the parent workflow.
+ */
+ public WorkflowTopologyNode getParent()
+ {
+ return parent;
+ }
+
+
+ /**
+ * Indicates whether the root workflow element is encapsulating a private
+ * local backend or not.
+ *
+ * @return <code>true</code> if the root workflow element encapsulates
+ * a private local backend
+ */
+ public boolean isPrivate()
+ {
+ return getWorkflowImpl().isPrivate();
+ }
+
+
+ /**
+ * Gets the base DN of the workflow that handles a given dn. The elected
+ * workflow may be the current workflow or one of its subordiante workflows.
+ *
+ * @param dn the DN for which we are looking a parent DN
+ * @return the base DN which is the parent of the <code>dn</code>,
+ * <code>null</code> if no parent DN was found
+ */
+ public DN getParentBaseDN(DN dn)
+ {
+ if (dn == null)
+ {
+ return null;
+ }
+
+ // parent base DN to return
+ DN parentBaseDN = null;
+
+ // Is the dn a subordinate of the current base DN?
+ DN curBaseDN = getBaseDN();
+ if (curBaseDN != null)
+ {
+ if (dn.isDescendantOf(curBaseDN))
+ {
+ // The dn may be handled by the current workflow.
+ // Now we have to check whether the dn is handled by
+ // a subordinate.
+ for (WorkflowTopologyNode subordinate: getSubordinates())
+ {
+ parentBaseDN = subordinate.getParentBaseDN(dn);
+ if (parentBaseDN != null)
+ {
+ // the dn is handled by a subordinate
+ break;
+ }
+ }
+
+ // If the dn is not handled by any subordinate, then it is
+ // handled by the current workflow.
+ if (parentBaseDN == null)
+ {
+ parentBaseDN = curBaseDN;
+ }
+ }
+ }
+
+ return parentBaseDN;
+ }
+
+
+ /**
+ * Adds a workflow to the list of workflow subordinates without
+ * additional control.
+ *
+ * @param newWorkflow the workflow to add to the subordinate list
+ * @param parentWorkflow the parent workflow of the new workflow
+ */
+ private void addSubordinateNoCheck(
+ WorkflowTopologyNode newWorkflow,
+ WorkflowTopologyNode parentWorkflow
+ )
+ {
+ subordinates.add(newWorkflow);
+ newWorkflow.setParent(parentWorkflow);
+ }
+
+
+ /**
+ * Adds a workflow to the subordinate list of the current workflow.
+ * Before we can add the new workflow, we have to check whether
+ * the new workflow is a parent workflow of any of the current
+ * subordinates (if so, then we have to add the subordinate in the
+ * subordinate list of the new workflow).
+ *
+ * @param newWorkflow the workflow to add in the subordinate list
+ */
+ private void addSubordinate(
+ WorkflowTopologyNode newWorkflow
+ )
+ {
+ // Check whether subordinates of current workflow should move to the
+ // new workflow subordinate list.
+ ArrayList<WorkflowTopologyNode> curSubordinateList =
+ new ArrayList<WorkflowTopologyNode>(getSubordinates());
+
+ for (WorkflowTopologyNode curSubordinate: curSubordinateList)
+ {
+ DN newDN = newWorkflow.getBaseDN();
+ DN subordinateDN = curSubordinate.getBaseDN();
+ if (subordinateDN.isDescendantOf(newDN))
+ {
+ removeSubordinate(curSubordinate);
+ newWorkflow.addSubordinateNoCheck(curSubordinate, newWorkflow);
+ }
+ }
+
+ // add the new workflow in the current workflow subordinate list
+ addSubordinateNoCheck(newWorkflow, this);
+ }
+
+
+ /**
+ * Remove a workflow from the subordinate list.
+ *
+ * @param subordinate the subordinate to remove from the subordinate list
+ */
+ public void removeSubordinate(
+ WorkflowTopologyNode subordinate
+ )
+ {
+ subordinates.remove(subordinate);
+ }
+
+
+ /**
+ * Tries to insert a new workflow in the subordinate list of one of the
+ * current workflow subordinate, or in the current workflow subordinate list.
+ *
+ * @param newWorkflow the new workflow to insert
+ *
+ * @return <code>true</code> if the new workflow has been inserted
+ * in any subordinate list
+ */
+ public boolean insertSubordinate(
+ WorkflowTopologyNode newWorkflow
+ )
+ {
+ // don't try to insert the workflow in itself!
+ if (newWorkflow == this)
+ {
+ return false;
+ }
+
+ // the returned status
+ boolean insertDone = false;
+
+ DN parentBaseDN = getBaseDN();
+ DN newBaseDN = newWorkflow.getBaseDN();
+
+ // dont' try to insert workflows when baseDNs are the same on both
+ // workflows
+ if (parentBaseDN.equals(newBaseDN))
+ {
+ return false;
+ }
+
+ // try to insert the new workflow
+ if (newBaseDN.isDescendantOf(parentBaseDN))
+ {
+ // the new workflow is a subordinate for this parent DN, let's
+ // insert the new workflow in the list of subordinates
+ for (WorkflowTopologyNode subordinate: getSubordinates())
+ {
+ insertDone = subordinate.insertSubordinate(newWorkflow);
+ if (insertDone)
+ {
+ // the newBaseDN is handled by a subordinate
+ break;
+ }
+ }
+
+ // if the newBaseDN is not handled by a subordinate then the workflow
+ // is inserted it in the current workflow subordinate list
+ if (! insertDone)
+ {
+ addSubordinate(newWorkflow);
+ insertDone = true;
+ }
+ }
+
+ return insertDone;
+ }
+
+
+ /**
+ * Removes the current workflow from the parent subordinate list
+ * and attach the workflow subordinates to the parent workflow.
+ *
+ * Example: the workflow to remove is w2
+ *
+ * w1 w1
+ * | / \
+ * w2 ==> w3 w4
+ * / \
+ * w3 w4
+ *
+ * - Subordinate list of w1 is updated with w3 and w4.
+ * - Parent workflow of w3 and w4 is now w1.
+ */
+ public void remove()
+ {
+ // First of all, remove the workflow from the parent subordinate list
+ WorkflowTopologyNode parent = getParent();
+ if (parent != null)
+ {
+ parent.removeSubordinate(this);
+ }
+
+ // Then set the parent of each subordinate and attach the subordinate to
+ // the parent.
+ for (WorkflowTopologyNode subordinate: getSubordinates())
+ {
+ subordinate.setParent(parent);
+ if (parent != null)
+ {
+ parent.addSubordinateNoCheck(subordinate, parent);
+ }
+ }
+ }
+
+
+ /**
+ * Gets the list of workflow subordinates.
+ *
+ * @return the list of workflow subordinates
+ */
+ public ArrayList<WorkflowTopologyNode> getSubordinates()
+ {
+ return subordinates;
+ }
+
+
+ /**
+ * Gets the highest workflow in the topology that can handle the requestDN.
+ * The highest workflow is either the current workflow or one of its
+ * subordinates.
+ *
+ * @param requestDN The DN for which we search for a workflow
+ * @return the highest workflow that can handle the requestDN
+ * <code>null</code> if none was found
+ */
+ public WorkflowTopologyNode getWorkflowCandidate(
+ DN requestDN
+ )
+ {
+ // the returned workflow
+ WorkflowTopologyNode workflowCandidate = null;
+
+ // does the current workflow handle the request baseDN?
+ DN baseDN = getParentBaseDN(requestDN);
+ if (baseDN == null)
+ {
+ // the current workflow does not handle the requestDN,
+ // let's return null
+ }
+ else
+ {
+ // is there any subordinate that can handle the requestDN?
+ for (WorkflowTopologyNode subordinate: getSubordinates())
+ {
+ workflowCandidate = subordinate.getWorkflowCandidate(requestDN);
+ if (workflowCandidate != null)
+ {
+ break;
+ }
+ }
+
+ // none of the subordinates can handle the requestDN, so the current
+ // workflow is the best root workflow candidate
+ if (workflowCandidate == null)
+ {
+ workflowCandidate = this;
+ }
+ }
+
+ return workflowCandidate;
+ }
+
+
+ /**
+ * Dumps info from the current workflow for debug purpose.
+ *
+ * @param leftMargin white spaces used to indent the traces
+ * @return a string buffer that contains trace information
+ */
+ public StringBuffer toString(String leftMargin)
+ {
+ StringBuffer sb = new StringBuffer();
+
+ // display the baseDN
+ DN baseDN = getBaseDN();
+ sb.append(leftMargin + "Workflow baseDN:[");
+ if (baseDN.isNullDN())
+ {
+ sb.append(" \"\"");
+ }
+ else
+ {
+ sb.append(" \"" + baseDN.toString() + "\"");
+ }
+ sb.append(" ]\n");
+
+ // display parent workflow
+ sb.append(leftMargin + "Parent: " + getParent() + "\n");
+
+ // dump each subordinate
+ sb.append(leftMargin + "List of subordinates:\n");
+ ArrayList<WorkflowTopologyNode> subordinates = getSubordinates();
+ if (subordinates.isEmpty())
+ {
+ sb.append(leftMargin + " NONE\n");
+ }
+ else
+ {
+ for (WorkflowTopologyNode subordinate: getSubordinates())
+ {
+ sb.append(subordinate.toString(leftMargin + " "));
+ }
+ }
+
+ return sb;
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
index 5e19363..95e2b05 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
@@ -35,7 +35,7 @@
import org.opends.server.admin.std.server.GroupImplementationCfg;
import org.opends.server.api.Group;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.config.ConfigException;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Attribute;
@@ -460,8 +460,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), requestControls,
groupEntryDN, mods);
modifyOperation.run();
@@ -524,8 +524,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), requestControls,
groupEntryDN, mods);
modifyOperation.run();
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkQueue.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkQueue.java
index 8953361..1a87228 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkQueue.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkQueue.java
@@ -61,6 +61,7 @@
import static org.opends.server.messages.ConfigMessages.*;
import static org.opends.server.messages.CoreMessages.*;
import static org.opends.server.messages.MessageHandler.*;
+import org.opends.server.types.AbstractOperation;
@@ -122,7 +123,7 @@
private int numWorkerThreads;
// The queue that will be used to actually hold the pending operations.
- private LinkedBlockingQueue<Operation> opQueue;
+ private LinkedBlockingQueue<AbstractOperation> opQueue;
// The lock used to provide threadsafe access for the queue.
private ReentrantLock queueLock;
@@ -167,11 +168,11 @@
// Create the actual work queue.
if (maxCapacity > 0)
{
- opQueue = new LinkedBlockingQueue<Operation>(maxCapacity);
+ opQueue = new LinkedBlockingQueue<AbstractOperation>(maxCapacity);
}
else
{
- opQueue = new LinkedBlockingQueue<Operation>();
+ opQueue = new LinkedBlockingQueue<AbstractOperation>();
}
@@ -295,8 +296,7 @@
* down or the pending operation queue is already
* at its maximum capacity).
*/
- @Override()
- public void submitOperation(Operation operation)
+ public void submitOperation(AbstractOperation operation)
throws DirectoryException
{
if (shutdownRequested)
@@ -331,7 +331,7 @@
* if the server is shutting down and no more operations will be
* processed.
*/
- public Operation nextOperation(TraditionalWorkerThread workerThread)
+ public AbstractOperation nextOperation(TraditionalWorkerThread workerThread)
{
return retryNextOperation(workerThread, 0);
}
@@ -354,7 +354,8 @@
* if the server is shutting down and no more operations will be
* processed, or if there have been too many consecutive failures.
*/
- private Operation retryNextOperation(TraditionalWorkerThread workerThread,
+ private AbstractOperation retryNextOperation(
+ TraditionalWorkerThread workerThread,
int numFailures)
{
// See if we should kill off this thread. This could be necessary if the
@@ -414,7 +415,7 @@
{
while (true)
{
- Operation nextOperation = opQueue.poll(5, TimeUnit.SECONDS);
+ AbstractOperation nextOperation = opQueue.poll(5, TimeUnit.SECONDS);
if (nextOperation == null)
{
// There was no work to do in the specified length of time. See if
@@ -512,7 +513,7 @@
* @return <CODE>true</CODE> if the provided request was present in the queue
* and was removed successfully, or <CODE>false</CODE> it not.
*/
- public boolean removeOperation(Operation operation)
+ public boolean removeOperation(AbstractOperation operation)
{
return opQueue.remove(operation);
}
@@ -642,20 +643,22 @@
try
{
- LinkedBlockingQueue<Operation> newOpQueue;
+ LinkedBlockingQueue<AbstractOperation> newOpQueue;
if (newMaxCapacity > 0)
{
- newOpQueue = new LinkedBlockingQueue<Operation>(newMaxCapacity);
+ newOpQueue =
+ new LinkedBlockingQueue<AbstractOperation>(newMaxCapacity);
}
else
{
- newOpQueue = new LinkedBlockingQueue<Operation>();
+ newOpQueue = new LinkedBlockingQueue<AbstractOperation>();
}
- LinkedBlockingQueue<Operation> oldOpQueue = opQueue;
+ LinkedBlockingQueue<AbstractOperation> oldOpQueue = opQueue;
opQueue = newOpQueue;
- LinkedList<Operation> pendingOps = new LinkedList<Operation>();
+ LinkedList<AbstractOperation> pendingOps =
+ new LinkedList<AbstractOperation>();
oldOpQueue.drainTo(pendingOps);
@@ -665,10 +668,10 @@
// loop a few times to get everything in there.
while (! pendingOps.isEmpty())
{
- Iterator<Operation> iterator = pendingOps.iterator();
+ Iterator<AbstractOperation> iterator = pendingOps.iterator();
while (iterator.hasNext())
{
- Operation o = iterator.next();
+ AbstractOperation o = iterator.next();
try
{
if (newOpQueue.offer(o, 1000, TimeUnit.MILLISECONDS))
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkerThread.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkerThread.java
index 4978266..5cd4053 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkerThread.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/TraditionalWorkerThread.java
@@ -32,13 +32,13 @@
import org.opends.server.api.DirectoryThread;
import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.Operation;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -72,7 +72,7 @@
private boolean waitingForWork;
// The operation that this worker thread is currently processing.
- private Operation operation;
+ private AbstractOperation operation;
// The handle to the actual thread for this worker thread.
private Thread workerThread;
@@ -221,8 +221,9 @@
String.valueOf(operation),
stackTraceToSingleLineString(e));
- operation.disconnectClient(DisconnectReason.SERVER_ERROR, true,
- message, msgID);
+ operation.disconnectClient(
+ DisconnectReason.SERVER_ERROR,
+ true, message, msgID);
}
catch (Exception e2)
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/loggers/TextAuditLogPublisher.java b/opendj-sdk/opends/src/server/org/opends/server/loggers/TextAuditLogPublisher.java
index aa85bab..9cb840f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/loggers/TextAuditLogPublisher.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/loggers/TextAuditLogPublisher.java
@@ -443,28 +443,26 @@
if(code == SUCCESS)
{
- Entry entry = addOperation.getEntryToAdd();
-
StringBuilder buffer = new StringBuilder(50);
buffer.append("# ");
buffer.append(TimeThread.getLocalTime());
buffer.append(EOL);
buffer.append("dn:");
- encodeValue(entry.getDN().toString(), buffer);
+ encodeValue(addOperation.getEntryDN().toString(), buffer);
buffer.append(EOL);
buffer.append("changetype: add");
buffer.append(EOL);
- for (String ocName : entry.getObjectClasses().values())
+ for (String ocName : addOperation.getObjectClasses().values())
{
buffer.append("objectClass: ");
buffer.append(ocName);
buffer.append(EOL);
}
- for (List<Attribute> attrList : entry.getUserAttributes().values())
+ for (List<Attribute> attrList : addOperation.getUserAttributes().values())
{
for (Attribute a : attrList)
{
@@ -478,7 +476,8 @@
}
}
- for (List<Attribute> attrList : entry.getOperationalAttributes().values())
+ for (List<Attribute> attrList :
+ addOperation.getOperationalAttributes().values())
{
for (Attribute a : attrList)
{
@@ -563,15 +562,13 @@
if(code == SUCCESS)
{
- Entry entry = deleteOperation.getEntryToDelete();
-
StringBuilder buffer = new StringBuilder(50);
buffer.append("# ");
buffer.append(TimeThread.getLocalTime());
buffer.append(EOL);
buffer.append("dn:");
- encodeValue(entry.getDN().toString(), buffer);
+ encodeValue(deleteOperation.getEntryDN().toString(), buffer);
buffer.append(EOL);
buffer.append("changetype: delete");
@@ -629,15 +626,13 @@
if(code == SUCCESS)
{
- Entry entry = modifyOperation.getModifiedEntry();
-
StringBuilder buffer = new StringBuilder(50);
buffer.append("# ");
buffer.append(TimeThread.getLocalTime());
buffer.append(EOL);
buffer.append("dn:");
- encodeValue(entry.getDN().toString(), buffer);
+ encodeValue(modifyOperation.getEntryDN().toString(), buffer);
buffer.append(EOL);
buffer.append("changetype: modify");
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java
index 276fe40..b6e7111 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6169,6 +6169,16 @@
CATEGORY_MASK_CORE | SEVERITY_MASK_NOTICE | 619;
+ /**
+ * The message ID for the message that will be used if a workflow is
+ * configured with no root workflow element. No root workflow element
+ * means no processing on the DIT attached to the workflow, which makes
+ * no sense.
+ */
+ public static final int MSGID_WARNING_ROOT_WORKFLOW_ELEMENT_NOT_DEFINED =
+ CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_WARNING | 620;
+
+
/**
* The message ID for the message that will be used if an attribute used an
@@ -8443,6 +8453,11 @@
"The Directory Server is leaving lockdown mode and will " +
"resume normal operation");
+ registerMessage(MSGID_WARNING_ROOT_WORKFLOW_ELEMENT_NOT_DEFINED,
+ "The workflow with base DN \"%s\" has no root workflow " +
+ "element"
+ );
+
registerMessage(MSGID_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN,
"Unable to decode the provided attribute because it " +
@@ -8458,6 +8473,10 @@
registerMessage(MSGID_ENTRYENCODECFG_INVALID_LENGTH,
"Unable to decode the provided entry encode " +
"configuration element because it has an invalid length");
+
+ registerMessage(MSGID_WARNING_ROOT_WORKFLOW_ELEMENT_NOT_DEFINED,
+ "The workflow with base DN \"%s\" has no root workflow " +
+ "element");
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
index 68f1295..64e3113 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalClientConnection.java
@@ -28,6 +28,13 @@
+import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.messages.ProtocolMessages.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.getExceptionMessage;
+
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -43,18 +50,11 @@
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.api.ConnectionSecurityProvider;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.BindOperation;
-import org.opends.server.core.CompareOperation;
-import org.opends.server.core.DeleteOperation;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ExtendedOperation;
-import org.opends.server.core.ModifyOperation;
-import org.opends.server.core.ModifyDNOperation;
-import org.opends.server.core.SearchOperation;
-import org.opends.server.extensions.
- InternalConnectionSecurityProvider;
+import org.opends.server.core.*;
+import org.opends.server.extensions.*;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AuthenticationInfo;
@@ -62,37 +62,29 @@
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.DirectoryException;
import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
import org.opends.server.types.IntermediateResponse;
-import org.opends.server.types.Modification;
import org.opends.server.types.LDAPException;
+import org.opends.server.types.Modification;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.Operation;
+import org.opends.server.types.RDN;
import org.opends.server.types.RawAttribute;
import org.opends.server.types.RawFilter;
import org.opends.server.types.RawModification;
import org.opends.server.types.ResultCode;
-import org.opends.server.types.RDN;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SearchResultReference;
import org.opends.server.types.SearchScope;
-import static org.opends.server.config.ConfigConstants.*;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-import static org.opends.server.messages.ProtocolMessages.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
/**
@@ -136,7 +128,7 @@
private AuthenticationInfo authenticationInfo;
// The empty operation list for this connection.
- private LinkedList<Operation> operationList;
+ private LinkedList<AbstractOperation> operationList;
// The connection ID for this client connection.
private long connectionID;
@@ -237,7 +229,7 @@
}
connectionID = nextConnectionID.getAndDecrement();
- operationList = new LinkedList<Operation>();
+ operationList = new LinkedList<AbstractOperation>();
try
{
@@ -274,7 +266,7 @@
super.setLookthroughLimit(0);
connectionID = nextConnectionID.getAndDecrement();
- operationList = new LinkedList<Operation>();
+ operationList = new LinkedList<AbstractOperation>();
try
{
@@ -693,8 +685,9 @@
public AddOperation processAdd(ByteString rawEntryDN,
List<RawAttribute> rawAttributes)
{
- AddOperation addOperation =
- new AddOperation(this, nextOperationID(), nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0), rawEntryDN,
rawAttributes);
addOperation.setInternalOperation(true);
@@ -728,8 +721,9 @@
Map<AttributeType,List<Attribute>>
operationalAttributes)
{
- AddOperation addOperation =
- new AddOperation(this, nextOperationID(), nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0), entryDN,
objectClasses, userAttributes,
operationalAttributes);
@@ -795,8 +789,9 @@
public BindOperation processSimpleBind(ByteString rawBindDN,
ByteString password)
{
- BindOperation bindOperation =
- new BindOperation(this, nextOperationID(), nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0),
PROTOCOL_VERSION, rawBindDN, password);
bindOperation.setInternalOperation(true);
@@ -822,8 +817,9 @@
public BindOperation processSimpleBind(DN bindDN,
ByteString password)
{
- BindOperation bindOperation =
- new BindOperation(this, nextOperationID(), nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0),
PROTOCOL_VERSION, bindDN, password);
bindOperation.setInternalOperation(true);
@@ -851,8 +847,9 @@
String saslMechanism,
ASN1OctetString saslCredentials)
{
- BindOperation bindOperation =
- new BindOperation(this, nextOperationID(), nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0),
PROTOCOL_VERSION, rawBindDN, saslMechanism,
saslCredentials);
@@ -881,8 +878,9 @@
String saslMechanism,
ASN1OctetString saslCredentials)
{
- BindOperation bindOperation =
- new BindOperation(this, nextOperationID(), nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0),
PROTOCOL_VERSION, bindDN, saslMechanism,
saslCredentials);
@@ -1010,8 +1008,9 @@
*/
public DeleteOperation processDelete(ByteString rawEntryDN)
{
- DeleteOperation deleteOperation =
- new DeleteOperation(this, nextOperationID(), nextMessageID(),
+ DeleteOperationBasis deleteOperation =
+ new DeleteOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0), rawEntryDN);
deleteOperation.setInternalOperation(true);
@@ -1033,8 +1032,9 @@
*/
public DeleteOperation processDelete(DN entryDN)
{
- DeleteOperation deleteOperation =
- new DeleteOperation(this, nextOperationID(), nextMessageID(),
+ DeleteOperationBasis deleteOperation =
+ new DeleteOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0), entryDN);
deleteOperation.setInternalOperation(true);
@@ -1066,7 +1066,6 @@
new ArrayList<Control>(0), requestOID,
requestValue);
extendedOperation.setInternalOperation(true);
-
extendedOperation.run();
return extendedOperation;
}
@@ -1111,13 +1110,14 @@
public ModifyOperation processModify(ByteString rawEntryDN,
List<RawModification> rawModifications)
{
- ModifyOperation modifyOperation =
- new ModifyOperation(this, nextOperationID(), nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0), rawEntryDN,
rawModifications);
modifyOperation.setInternalOperation(true);
-
modifyOperation.run();
+
return modifyOperation;
}
@@ -1138,13 +1138,14 @@
public ModifyOperation processModify(DN entryDN,
List<Modification> modifications)
{
- ModifyOperation modifyOperation =
- new ModifyOperation(this, nextOperationID(), nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(this, nextOperationID(),
+ nextMessageID(),
new ArrayList<Control>(0), entryDN,
modifications);
modifyOperation.setInternalOperation(true);
-
modifyOperation.run();
+
return modifyOperation;
}
@@ -1832,7 +1833,7 @@
* @return The set of operations in progress for this client
* connection.
*/
- public Collection<Operation> getOperationsInProgress()
+ public Collection<AbstractOperation> getOperationsInProgress()
{
return operationList;
}
@@ -1849,7 +1850,7 @@
* or <CODE>null</CODE> if no such operation could be
* found.
*/
- public Operation getOperationInProgress(int messageID)
+ public AbstractOperation getOperationInProgress(int messageID)
{
// Internal operations will not be tracked.
return null;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalSearchOperation.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalSearchOperation.java
index 3e1a2a1..91010af 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalSearchOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/internal/InternalSearchOperation.java
@@ -33,7 +33,7 @@
import java.util.List;
import org.opends.server.api.ClientConnection;
-import org.opends.server.core.SearchOperation;
+import org.opends.server.core.SearchOperationBasis;
import org.opends.server.types.ByteString;
import org.opends.server.types.Control;
import org.opends.server.types.DN;
@@ -55,7 +55,7 @@
* client since there is no real client.
*/
public class InternalSearchOperation
- extends SearchOperation
+ extends SearchOperationBasis
{
// The internal search listener for this search, if one was
// provided.
@@ -284,5 +284,26 @@
searchReference);
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void sendSearchEntry(SearchResultEntry searchEntry)
+ throws DirectoryException
+ {
+ addSearchEntry(searchEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean sendSearchReference(SearchResultReference
+ searchReference)
+ throws DirectoryException
+ {
+ addSearchReference(searchReference);
+ return true;
+ }
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
index bd282b3..67c2fd6 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxClientConnection.java
@@ -43,6 +43,7 @@
import org.opends.server.protocols.internal.InternalSearchOperation ;
import org.opends.server.protocols.internal.InternalSearchListener;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.CancelRequest;
@@ -88,7 +89,7 @@
private ConnectionSecurityProvider securityProvider;
// The empty operation list for this connection.
- private LinkedList<Operation> operationList;
+ private LinkedList<AbstractOperation> operationList;
// The connection ID for this client connection.
private long connectionID;
@@ -142,7 +143,7 @@
true,
MSGID_LDAP_CONNHANDLER_REJECTED_BY_SERVER);
}
- operationList = new LinkedList<Operation>();
+ operationList = new LinkedList<AbstractOperation>();
try
{
@@ -468,11 +469,11 @@
* @return A reference to the add operation that was processed and contains
* information about the result of the processing.
*/
- public AddOperation processAdd(ASN1OctetString rawEntryDN,
+ public AddOperationBasis processAdd(ASN1OctetString rawEntryDN,
ArrayList<RawAttribute> rawAttributes)
{
- AddOperation addOperation =
- new AddOperation(this, nextOperationID(), nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(this, nextOperationID(), nextMessageID(),
new ArrayList<Control>(0), rawEntryDN, rawAttributes);
addOperation.run();
@@ -514,10 +515,10 @@
* @return A reference to the delete operation that was processed and
* contains information about the result of the processing.
*/
- public DeleteOperation processDelete(ASN1OctetString rawEntryDN)
+ public DeleteOperationBasis processDelete(ASN1OctetString rawEntryDN)
{
- DeleteOperation deleteOperation =
- new DeleteOperation(this, nextOperationID(), nextMessageID(),
+ DeleteOperationBasis deleteOperation =
+ new DeleteOperationBasis(this, nextOperationID(), nextMessageID(),
new ArrayList<Control>(0), rawEntryDN);
deleteOperation.run();
@@ -560,11 +561,11 @@
* @return A reference to the modify operation that was processed and
* contains information about the result of the processing
*/
- public ModifyOperation processModify(ASN1OctetString rawEntryDN,
+ public ModifyOperationBasis processModify(ASN1OctetString rawEntryDN,
ArrayList<RawModification> rawModifications)
{
- ModifyOperation modifyOperation =
- new ModifyOperation(this, nextOperationID(), nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(this, nextOperationID(), nextMessageID(),
new ArrayList<Control>(0), rawEntryDN,
rawModifications);
@@ -714,8 +715,6 @@
typesOnly, filter, attributes,
searchListener);
-
-
searchOperation.run();
return searchOperation;
}
@@ -826,6 +825,7 @@
{
UnbindOperation unbindOp = new UnbindOperation((ClientConnection) this,
this.nextOperationID(), this.nextMessageID(), null);
+
unbindOp.run();
}
catch (Exception e)
@@ -894,7 +894,7 @@
*
* @return The set of operations in progress for this client connection.
*/
- public Collection<Operation> getOperationsInProgress()
+ public Collection<AbstractOperation> getOperationsInProgress()
{
return operationList;
}
@@ -909,7 +909,7 @@
* @return The operation in progress with the specified message ID, or
* <CODE>null</CODE> if no such operation could be found.
*/
- public Operation getOperationInProgress(int messageID)
+ public AbstractOperation getOperationInProgress(int messageID)
{
// Jmx operations will not be tracked.
return null;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java
index 70e6069..47bb286 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiAuthenticator.java
@@ -32,7 +32,7 @@
import javax.security.auth.Subject;
import org.opends.server.api.plugin.PostConnectPluginResult;
-import org.opends.server.core.BindOperation;
+import org.opends.server.core.BindOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.PluginConfigManager;
import org.opends.server.messages.CoreMessages;
@@ -261,7 +261,7 @@
JmxClientConnection jmxClientConnection = new JmxClientConnection(
jmxConnectionHandler, authInfo);
- BindOperation bindOp = new BindOperation(jmxClientConnection,
+ BindOperationBasis bindOp = new BindOperationBasis(jmxClientConnection,
jmxClientConnection.nextOperationID(),
jmxClientConnection.nextMessageID(), requestControls,
jmxConnectionHandler.getRMIConnector().getProtocolVersion(),
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
index 802cb00..7b052bd 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -28,6 +28,17 @@
+import static org.opends.server.loggers.AccessLogger.logDisconnect;
+import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.messages.ProtocolMessages.*;
+import static org.opends.server.protocols.ldap.LDAPConstants.*;
+import static org.opends.server.util.StaticUtils.getBacktrace;
+import static org.opends.server.util.StaticUtils.getExceptionMessage;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
@@ -43,30 +54,34 @@
import org.opends.server.api.ConnectionHandler;
import org.opends.server.api.ConnectionSecurityProvider;
import org.opends.server.core.AbandonOperation;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.BindOperation;
+import org.opends.server.core.AddOperationBasis;
+import org.opends.server.core.BindOperationBasis;
import org.opends.server.core.CompareOperation;
-import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ExtendedOperation;
-import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.core.PersistentSearch;
import org.opends.server.core.PluginConfigManager;
import org.opends.server.core.SearchOperation;
+import org.opends.server.core.SearchOperationBasis;
import org.opends.server.core.UnbindOperation;
import org.opends.server.extensions.NullConnectionSecurityProvider;
import org.opends.server.extensions.TLSCapableConnection;
import org.opends.server.extensions.TLSConnectionSecurityProvider;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.asn1.ASN1Sequence;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DisconnectReason;
-import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.IntermediateResponse;
@@ -75,16 +90,6 @@
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SearchResultReference;
-import static org.opends.server.loggers.AccessLogger.*;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.messages.ProtocolMessages.*;
-import static org.opends.server.protocols.ldap.LDAPConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
/**
@@ -127,7 +132,7 @@
private byte[] elementValue;
// The set of all operations currently in progress on this connection.
- private ConcurrentHashMap<Integer,Operation> operationsInProgress;
+ private ConcurrentHashMap<Integer,AbstractOperation> operationsInProgress;
// The connection security provider that was in use for the client connection
// before switching to a TLS-based provider.
@@ -239,7 +244,7 @@
nextOperationID = new AtomicLong(0);
connectionValid = true;
disconnectRequested = false;
- operationsInProgress = new ConcurrentHashMap<Integer,Operation>();
+ operationsInProgress = new ConcurrentHashMap<Integer,AbstractOperation>();
keepStats = connectionHandler.keepStats();
protocol = "LDAP";
@@ -624,7 +629,7 @@
break;
case BIND:
ASN1OctetString serverSASLCredentials =
- ((BindOperation) operation).getServerSASLCredentials();
+ ((BindOperationBasis) operation).getServerSASLCredentials();
protocolOp = new BindResponseProtocolOp(resultCode.getIntValue(),
errorMessage.toString(), matchedDN,
referralURLs, serverSASLCredentials);
@@ -1117,7 +1122,7 @@
*
* @return The set of operations in progress for this client connection.
*/
- public Collection<Operation> getOperationsInProgress()
+ public Collection<AbstractOperation> getOperationsInProgress()
{
return operationsInProgress.values();
}
@@ -1132,7 +1137,7 @@
* @return The operation in progress with the specified message ID, or
* <CODE>null</CODE> if no such operation could be found.
*/
- public Operation getOperationInProgress(int messageID)
+ public AbstractOperation getOperationInProgress(int messageID)
{
return operationsInProgress.get(messageID);
}
@@ -1150,7 +1155,7 @@
* (e.g., the client already has reached the
* maximum allowed concurrent requests).
*/
- public void addOperationInProgress(Operation operation)
+ public void addOperationInProgress(AbstractOperation operation)
throws DirectoryException
{
int messageID = operation.getMessageID();
@@ -1174,7 +1179,7 @@
// See if there is already an operation in progress with the same message
// ID. If so, then we can't allow it.
- Operation op = operationsInProgress.get(messageID);
+ AbstractOperation op = operationsInProgress.get(messageID);
if (op != null)
{
int msgID = MSGID_LDAP_CLIENT_DUPLICATE_MESSAGE_ID;
@@ -1235,7 +1240,7 @@
*/
public boolean removeOperationInProgress(int messageID)
{
- Operation operation = operationsInProgress.remove(messageID);
+ AbstractOperation operation = operationsInProgress.remove(messageID);
return (operation != null);
}
@@ -1254,7 +1259,7 @@
public CancelResult cancelOperation(int messageID,
CancelRequest cancelRequest)
{
- Operation op = operationsInProgress.get(messageID);
+ AbstractOperation op = operationsInProgress.get(messageID);
if (op == null)
{
// See if the operation is in the list of persistent searches.
@@ -1303,7 +1308,7 @@
try
{
- for (Operation o : operationsInProgress.values())
+ for (AbstractOperation o : operationsInProgress.values())
{
try
{
@@ -1369,7 +1374,7 @@
continue;
}
- Operation o = operationsInProgress.get(msgID);
+ AbstractOperation o = operationsInProgress.get(msgID);
if (o != null)
{
try
@@ -1854,8 +1859,8 @@
{
// Create the add operation and add it into the work queue.
AddRequestProtocolOp protocolOp = message.getAddRequestProtocolOp();
- AddOperation addOp =
- new AddOperation(this, nextOperationID.getAndIncrement(),
+ AddOperationBasis addOp =
+ new AddOperationBasis(this, nextOperationID.getAndIncrement(),
message.getMessageID(), controls, protocolOp.getDN(),
protocolOp.getAttributes());
@@ -1933,17 +1938,17 @@
ASN1OctetString bindDN = protocolOp.getDN();
- BindOperation bindOp;
+ BindOperationBasis bindOp;
switch (protocolOp.getAuthenticationType())
{
case SIMPLE:
- bindOp = new BindOperation(this, nextOperationID.getAndIncrement(),
+ bindOp = new BindOperationBasis(this, nextOperationID.getAndIncrement(),
message.getMessageID(), controls,
versionString, bindDN,
protocolOp.getSimplePassword());
break;
case SASL:
- bindOp = new BindOperation(this, nextOperationID.getAndIncrement(),
+ bindOp = new BindOperationBasis(this, nextOperationID.getAndIncrement(),
message.getMessageID(), controls,
versionString, bindDN,
protocolOp.getSASLMechanism(),
@@ -1960,7 +1965,6 @@
return false;
}
-
// Add the operation into the work queue.
try
{
@@ -2019,7 +2023,6 @@
protocolOp.getDN(), protocolOp.getAttributeType(),
protocolOp.getAssertionValue());
-
// Add the operation into the work queue.
try
{
@@ -2064,12 +2067,11 @@
ArrayList<Control> controls)
{
DeleteRequestProtocolOp protocolOp = message.getDeleteRequestProtocolOp();
- DeleteOperation deleteOp =
- new DeleteOperation(this, nextOperationID.getAndIncrement(),
+ DeleteOperationBasis deleteOp =
+ new DeleteOperationBasis(this, nextOperationID.getAndIncrement(),
message.getMessageID(), controls,
protocolOp.getDN());
-
// Add the operation into the work queue.
try
{
@@ -2139,7 +2141,6 @@
message.getMessageID(), controls,
protocolOp.getOID(), protocolOp.getValue());
-
// Add the operation into the work queue.
try
{
@@ -2184,12 +2185,11 @@
ArrayList<Control> controls)
{
ModifyRequestProtocolOp protocolOp = message.getModifyRequestProtocolOp();
- ModifyOperation modifyOp =
- new ModifyOperation(this, nextOperationID.getAndIncrement(),
+ ModifyOperationBasis modifyOp =
+ new ModifyOperationBasis(this, nextOperationID.getAndIncrement(),
message.getMessageID(), controls,
protocolOp.getDN(), protocolOp.getModifications());
-
// Add the operation into the work queue.
try
{
@@ -2241,7 +2241,6 @@
protocolOp.deleteOldRDN(),
protocolOp.getNewSuperior());
-
// Add the operation into the work queue.
try
{
@@ -2286,8 +2285,8 @@
ArrayList<Control> controls)
{
SearchRequestProtocolOp protocolOp = message.getSearchRequestProtocolOp();
- SearchOperation searchOp =
- new SearchOperation(this, nextOperationID.getAndIncrement(),
+ SearchOperationBasis searchOp =
+ new SearchOperationBasis(this, nextOperationID.getAndIncrement(),
message.getMessageID(), controls,
protocolOp.getBaseDN(), protocolOp.getScope(),
protocolOp.getDereferencePolicy(),
@@ -2296,7 +2295,6 @@
protocolOp.getTypesOnly(), protocolOp.getFilter(),
protocolOp.getAttributes());
-
// Add the operation into the work queue.
try
{
@@ -2346,7 +2344,6 @@
unbindOp.run();
-
// The client connection will never be valid after an unbind.
return false;
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
index 91bdc28..969c1e0 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
@@ -52,7 +52,7 @@
import org.opends.server.types.ErrorLogSeverity;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
-
+import org.opends.server.workflowelement.localbackend.*;
/**
* This class is used to store historical information that is
@@ -146,7 +146,7 @@
*
* @param modifyOperation the modification.
*/
- public void generateState(ModifyOperation modifyOperation)
+ public void generateState(LocalBackendModifyOperation modifyOperation)
{
List<Modification> mods = modifyOperation.getModifications();
Entry modifiedEntry = modifyOperation.getModifiedEntry();
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
index 27a2466..5c02af2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
@@ -41,11 +41,8 @@
import org.opends.server.api.RestoreTaskListener;
import org.opends.server.api.SynchronizationProvider;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyDNOperation;
-import org.opends.server.core.ModifyOperation;
import org.opends.server.types.BackupConfig;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
@@ -58,6 +55,7 @@
import org.opends.server.types.RestoreConfig;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SynchronizationProviderResult;
+import org.opends.server.workflowelement.localbackend.*;
import static org.opends.server.messages.ReplicationMessages.*;
@@ -214,7 +212,7 @@
* {@inheritDoc}
*/
@Override
- public void doPostOperation(AddOperation addOperation)
+ public void doPostOperation(LocalBackendAddOperation addOperation)
{
DN dn = addOperation.getEntryDN();
genericPostOperation(addOperation, dn);
@@ -225,7 +223,7 @@
* {@inheritDoc}
*/
@Override
- public void doPostOperation(DeleteOperation deleteOperation)
+ public void doPostOperation(LocalBackendDeleteOperation deleteOperation)
{
DN dn = deleteOperation.getEntryDN();
genericPostOperation(deleteOperation, dn);
@@ -245,7 +243,7 @@
* {@inheritDoc}
*/
@Override
- public void doPostOperation(ModifyOperation modifyOperation)
+ public void doPostOperation(LocalBackendModifyOperation modifyOperation)
{
DN dn = modifyOperation.getEntryDN();
genericPostOperation(modifyOperation, dn);
@@ -256,7 +254,7 @@
*/
@Override
public SynchronizationProviderResult handleConflictResolution(
- ModifyOperation modifyOperation)
+ LocalBackendModifyOperation modifyOperation)
{
ReplicationDomain domain =
findDomain(modifyOperation.getEntryDN(), modifyOperation);
@@ -271,7 +269,7 @@
*/
@Override
public SynchronizationProviderResult handleConflictResolution(
- AddOperation addOperation) throws DirectoryException
+ LocalBackendAddOperation addOperation) throws DirectoryException
{
ReplicationDomain domain =
findDomain(addOperation.getEntryDN(), addOperation);
@@ -286,7 +284,7 @@
*/
@Override
public SynchronizationProviderResult handleConflictResolution(
- DeleteOperation deleteOperation) throws DirectoryException
+ LocalBackendDeleteOperation deleteOperation) throws DirectoryException
{
ReplicationDomain domain =
findDomain(deleteOperation.getEntryDN(), deleteOperation);
@@ -316,7 +314,7 @@
*/
@Override
public SynchronizationProviderResult
- doPreOperation(ModifyOperation modifyOperation)
+ doPreOperation(LocalBackendModifyOperation modifyOperation)
{
DN operationDN = modifyOperation.getEntryDN();
ReplicationDomain domain = findDomain(operationDN, modifyOperation);
@@ -343,7 +341,7 @@
*/
@Override
public SynchronizationProviderResult doPreOperation(
- DeleteOperation deleteOperation) throws DirectoryException
+ LocalBackendDeleteOperation deleteOperation) throws DirectoryException
{
return new SynchronizationProviderResult(true);
}
@@ -362,7 +360,8 @@
* {@inheritDoc}
*/
@Override
- public SynchronizationProviderResult doPreOperation(AddOperation addOperation)
+ public SynchronizationProviderResult doPreOperation(
+ LocalBackendAddOperation addOperation)
{
ReplicationDomain domain =
findDomain(addOperation.getEntryDN(), addOperation);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java
index 0579de3..7702c2d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java
@@ -36,7 +36,7 @@
import java.util.List;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
@@ -218,15 +218,14 @@
ArrayList<RawModification> mods = new ArrayList<RawModification>(1);
mods.add(mod);
- ModifyOperation op =
- new ModifyOperation(conn, InternalClientConnection.nextOperationID(),
+ ModifyOperationBasis op =
+ new ModifyOperationBasis(conn, InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(0), asn1BaseDn,
mods);
op.setInternalOperation(true);
op.setSynchronizationOperation(true);
op.setDontSynchronize(true);
-
op.run();
ResultCode result = op.getResultCode();
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
index ed7b98a..29f3aa6 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
@@ -68,6 +68,7 @@
import org.opends.server.core.LockFileManager;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1Exception;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
@@ -93,6 +94,7 @@
import org.opends.server.tasks.InitializeTargetTask;
import org.opends.server.tasks.InitializeTask;
import org.opends.server.tasks.TaskUtils;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
@@ -115,6 +117,7 @@
import org.opends.server.types.SearchResultEntry;
import org.opends.server.types.SearchScope;
import org.opends.server.types.SynchronizationProviderResult;
+import org.opends.server.workflowelement.localbackend.*;
/**
* This class implements the bulk part of the.of the Directory Server side
@@ -420,7 +423,7 @@
* can continue.
*/
public SynchronizationProviderResult handleConflictResolution(
- DeleteOperation deleteOperation)
+ LocalBackendDeleteOperation deleteOperation)
{
if ((!deleteOperation.isSynchronizationOperation())
&& (!brokerIsConnected(deleteOperation)))
@@ -674,7 +677,7 @@
* @return code indicating is operation must proceed
*/
public SynchronizationProviderResult handleConflictResolution(
- ModifyOperation modifyOperation)
+ LocalBackendModifyOperation modifyOperation)
{
if ((!modifyOperation.isSynchronizationOperation())
&& (!brokerIsConnected(modifyOperation)))
@@ -1203,8 +1206,7 @@
op.setInternalOperation(true);
op.setSynchronizationOperation(true);
changeNumber = OperationContext.getChangeNumber(op);
-
- op.run();
+ ((AbstractOperation)op).run();
ResultCode result = op.getResultCode();
@@ -2863,7 +2865,7 @@
public void synchronizeModifications(List<Modification> modifications)
{
Operation op =
- new ModifyOperation(InternalClientConnection.getRootConnection(),
+ new ModifyOperationBasis(InternalClientConnection.getRootConnection(),
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
null, DirectoryServer.getSchemaDN(),
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
index 299bcfa..84625ad 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
@@ -27,6 +27,7 @@
package org.opends.server.replication.protocol;
import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1Exception;
@@ -199,7 +200,7 @@
attr.add(LDAPAttribute.decode(elem));
}
- AddOperation add = new AddOperation(connection,
+ AddOperationBasis add = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(), null,
new ASN1OctetString(newDn), attr);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java
index cea0321..d8ba12b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/DeleteMsg.java
@@ -32,6 +32,7 @@
import java.util.zip.DataFormatException;
import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.common.ChangeNumber;
@@ -90,7 +91,7 @@
public Operation createOperation(InternalClientConnection connection,
String newDn)
{
- DeleteOperation del = new DeleteOperation(connection,
+ DeleteOperationBasis del = new DeleteOperationBasis(connection,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(), null,
new ASN1OctetString(newDn));
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
index aff4180..52fb3e2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/ModifyMsg.java
@@ -29,6 +29,7 @@
import static org.opends.server.replication.protocol.OperationContext.*;
import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1Exception;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.ldap.LDAPAttribute;
@@ -148,7 +149,7 @@
for (ASN1Element elem : mods)
ldapmods.add(LDAPModification.decode(elem));
- ModifyOperation mod = new ModifyOperation(connection,
+ ModifyOperationBasis mod = new ModifyOperationBasis(connection,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(), null,
new ASN1OctetString(newDn), ldapmods);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/AbstractOperation.java b/opendj-sdk/opends/src/server/org/opends/server/types/AbstractOperation.java
new file mode 100644
index 0000000..163fddd
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/types/AbstractOperation.java
@@ -0,0 +1,691 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.types;
+
+
+
+import static org.opends.server.core.CoreConstants.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.opends.server.api.ClientConnection;
+import org.opends.server.types.operation.PostResponseOperation;
+import org.opends.server.types.operation.PreParseOperation;
+import org.opends.server.core.DirectoryServer;
+
+
+
+/**
+ * This class defines a generic operation that may be processed by the
+ * Directory Server. Specific subclasses should implement specific
+ * functionality appropriate for the type of operation.
+ * <BR><BR>
+ * Note that this class is not intended to be subclassed by any
+ * third-party code outside of the OpenDS project. It should only be
+ * extended by the operation types included in the
+ * {@code org.opends.server.core} package.
+ */
+public abstract class AbstractOperation
+ implements Operation, PreParseOperation, PostResponseOperation,
+ Runnable
+{
+ /**
+ * The set of response controls that will always be returned for
+ * an abandon operation.
+ */
+ protected static final List<Control> NO_RESPONSE_CONTROLS =
+ new ArrayList<Control>(0);
+
+ /**
+ * The client connection with which this operation is associated.
+ */
+ protected final ClientConnection clientConnection;
+
+
+ /**
+ * The message ID for this operation.
+ */
+ protected final int messageID;
+
+
+
+ /**
+ * The operation ID for this operation.
+ */
+ protected final long operationID;
+
+
+
+ // Indicates whether this is an internal operation triggered within
+ // the server itself rather than requested by an external client.
+ private boolean isInternalOperation;
+
+ // Indicates whether this operation is involved in data
+ // synchronization processing.
+ private boolean isSynchronizationOperation;
+
+ // The cancel result for this operation.
+ private CancelResult cancelResult;
+
+ // The matched DN for this operation.
+ private DN matchedDN;
+
+ // The entry for the authorization identify for this operation.
+ private Entry authorizationEntry;
+
+ // A set of attachments associated with this operation that might
+ // be used by various components during its processing.
+ private Map<String,Object> attachments;
+
+ // The set of controls included in the request from the client.
+ private List<Control> requestControls;
+
+ // The set of referral URLs for this operation.
+ private List<String> referralURLs;
+
+ // The result code for this operation.
+ private ResultCode resultCode;
+
+ // Additional information that should be included in the log but
+ // not sent to the client.
+ private StringBuilder additionalLogMessage;
+
+ // The error message for this operation that should be included in
+ // the log and in the response to the client.
+ private StringBuilder errorMessage;
+
+ // Indicates whether this operation nneds to be synchronized to
+ // other copies of the data.
+ private boolean dontSynchronizeFlag;
+
+ // The time that processing started on this operation.
+ private long processingStartTime;
+
+ // The time that processing ended on this operation.
+ private long processingStopTime;
+
+ /**
+ * Creates a new operation with the provided information.
+ *
+ * @param clientConnection The client connection with which this
+ * operation is associated.
+ * @param operationID The identifier assigned to this
+ * operation for the client connection.
+ * @param messageID The message ID of the request with
+ * which this operation is associated.
+ * @param requestControls The set of controls included in the
+ * request.
+ */
+ protected AbstractOperation(ClientConnection clientConnection,
+ long operationID,
+ int messageID, List<Control> requestControls)
+ {
+ this.clientConnection = clientConnection;
+ this.operationID = operationID;
+ this.messageID = messageID;
+
+ if (requestControls == null)
+ {
+ this.requestControls = new ArrayList<Control>(0);
+ }
+ else
+ {
+ this.requestControls = requestControls;
+ }
+
+ resultCode = ResultCode.UNDEFINED;
+ additionalLogMessage = new StringBuilder();
+ errorMessage = new StringBuilder();
+ attachments = new HashMap<String,Object>();
+ matchedDN = null;
+ referralURLs = null;
+ cancelResult = null;
+ isInternalOperation = false;
+ isSynchronizationOperation = false;
+ authorizationEntry =
+ clientConnection.getAuthenticationInfo().
+ getAuthorizationEntry();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract OperationType getOperationType();
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract void disconnectClient(
+ DisconnectReason disconnectReason,
+ boolean sendNotification,
+ String message, int messageID);
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String[][] getCommonLogElements()
+ {
+ // Note that no debugging will be done in this method because
+ // it is a likely candidate for being called by the logging
+ // subsystem.
+
+ return new String[][]
+ {
+ new String[] { LOG_ELEMENT_CONNECTION_ID,
+ String.valueOf(getConnectionID()) },
+ new String[] { LOG_ELEMENT_OPERATION_ID,
+ String.valueOf(operationID) },
+ new String[] { LOG_ELEMENT_MESSAGE_ID,
+ String.valueOf(messageID) }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract String[][] getRequestLogElements();
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract String[][] getResponseLogElements();
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ClientConnection getClientConnection()
+ {
+ return clientConnection;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getConnectionID()
+ {
+ return clientConnection.getConnectionID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getOperationID()
+ {
+ return operationID;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int getMessageID()
+ {
+ return messageID;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final List<Control> getRequestControls()
+ {
+ return requestControls;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void addRequestControl(Control control)
+ {
+ requestControls.add(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void removeRequestControl(Control control)
+ {
+ requestControls.remove(control);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract List<Control> getResponseControls();
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract void addResponseControl(Control control);
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract void removeResponseControl(Control control);
+
+ /**
+ * {@inheritDoc}
+ */
+ public final ResultCode getResultCode()
+ {
+ return resultCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setResultCode(ResultCode resultCode)
+ {
+ this.resultCode = resultCode;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final StringBuilder getErrorMessage()
+ {
+ return errorMessage;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setErrorMessage(StringBuilder errorMessage)
+ {
+ if (errorMessage == null)
+ {
+ this.errorMessage = new StringBuilder();
+ }
+ else
+ {
+ this.errorMessage = errorMessage;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void appendErrorMessage(String message)
+ {
+ if (errorMessage == null)
+ {
+ errorMessage = new StringBuilder(message);
+ }
+ else
+ {
+ if (errorMessage.length() > 0)
+ {
+ errorMessage.append(" ");
+ }
+
+ errorMessage.append(message);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final StringBuilder getAdditionalLogMessage()
+ {
+ return additionalLogMessage;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setAdditionalLogMessage(StringBuilder
+ additionalLogMessage)
+ {
+ if (additionalLogMessage == null)
+ {
+ this.additionalLogMessage = new StringBuilder();
+ }
+ else
+ {
+ this.additionalLogMessage = additionalLogMessage;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void appendAdditionalLogMessage(String message)
+ {
+ if (additionalLogMessage == null)
+ {
+ additionalLogMessage = new StringBuilder(message);
+ }
+ else
+ {
+ additionalLogMessage.append(message);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getMatchedDN()
+ {
+ return matchedDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setMatchedDN(DN matchedDN)
+ {
+ this.matchedDN = matchedDN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final List<String> getReferralURLs()
+ {
+ return referralURLs;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setReferralURLs(List<String> referralURLs)
+ {
+ this.referralURLs = referralURLs;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setResponseData(DirectoryException
+ directoryException)
+ {
+ this.resultCode = directoryException.getResultCode();
+ this.matchedDN = directoryException.getMatchedDN();
+ this.referralURLs = directoryException.getReferralURLs();
+
+ appendErrorMessage(directoryException.getErrorMessage());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final boolean isInternalOperation()
+ {
+ return isInternalOperation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setInternalOperation(boolean isInternalOperation)
+ {
+ this.isInternalOperation = isInternalOperation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final boolean isSynchronizationOperation()
+ {
+ return isSynchronizationOperation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setSynchronizationOperation(
+ boolean isSynchronizationOperation)
+ {
+ this.isSynchronizationOperation = isSynchronizationOperation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setDontSynchronize(boolean dontSynchronize)
+ {
+ this.dontSynchronizeFlag = dontSynchronize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Entry getAuthorizationEntry()
+ {
+ return authorizationEntry;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setAuthorizationEntry(Entry authorizationEntry)
+ {
+ this.authorizationEntry = authorizationEntry;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final DN getAuthorizationDN()
+ {
+ if (authorizationEntry == null)
+ {
+ return DN.nullDN();
+ }
+ else
+ {
+ return authorizationEntry.getDN();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Map<String,Object> getAttachments()
+ {
+ return attachments;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Object getAttachment(String name)
+ {
+ return attachments.get(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Object removeAttachment(String name)
+ {
+ return attachments.remove(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final Object setAttachment(String name, Object value)
+ {
+ return attachments.put(name, value);
+ }
+
+ /**
+ * Performs the work of actually processing this operation.
+ * This should include all processing for the operation, including
+ * invoking plugins, logging messages, performing access control,
+ * managing synchronization, and any other work that might need to
+ * be done in the course of processing.
+ */
+ /*public abstract void run();*/
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void operationCompleted()
+ {
+ // Notify the client connection that this operation is complete
+ // and that it no longer needs to be retained.
+ clientConnection.removeOperationInProgress(messageID);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract CancelResult cancel(CancelRequest cancelRequest);
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract boolean setCancelRequest(CancelRequest
+ cancelRequest);
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract CancelRequest getCancelRequest();
+
+ /**
+ * {@inheritDoc}
+ */
+ public final CancelResult getCancelResult()
+ {
+ return cancelResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setCancelResult(CancelResult cancelResult)
+ {
+ this.cancelResult = cancelResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void indicateCancelled(CancelRequest cancelRequest)
+ {
+ setCancelResult(CancelResult.CANCELED);
+
+ if (cancelRequest.notifyOriginalRequestor() ||
+ DirectoryServer.notifyAbandonedOperations())
+ {
+ setResultCode(ResultCode.CANCELED);
+
+ String cancelReason = cancelRequest.getCancelReason();
+ if (cancelReason != null)
+ {
+ appendErrorMessage(cancelReason);
+ }
+
+ clientConnection.sendResponse(this);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String toString()
+ {
+ StringBuilder buffer = new StringBuilder();
+ toString(buffer);
+ return buffer.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract void toString(StringBuilder buffer);
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean dontSynchronize()
+ {
+ return dontSynchronizeFlag;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setAttachments(Map<String, Object> attachments){
+ this.attachments = attachments;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getProcessingStartTime()
+ {
+ return processingStartTime;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getProcessingStopTime()
+ {
+ return processingStopTime;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setProcessingStopTime()
+ {
+ this.processingStopTime = System.currentTimeMillis();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void setProcessingStartTime()
+ {
+ processingStartTime = System.currentTimeMillis();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final long getProcessingTime()
+ {
+ return (processingStopTime - processingStartTime);
+ }
+
+ /**
+ * Performs the work of actually processing this operation. This
+ * should include all processing for the operation, including
+ * invoking pre-parse and post-response plugins, logging messages
+ * and any other work that might need to be done in the course of
+ * processing.
+ */
+ public abstract void run();
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/Operation.java b/opendj-sdk/opends/src/server/org/opends/server/types/Operation.java
index 2e53740..23020cb 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/Operation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/types/Operation.java
@@ -28,156 +28,31 @@
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opends.server.api.ClientConnection;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.operation.PostOperationOperation;
-import org.opends.server.types.operation.PostResponseOperation;
-import org.opends.server.types.operation.PreOperationOperation;
-import org.opends.server.types.operation.PreParseOperation;
-
-import static org.opends.server.core.CoreConstants.*;
-
/**
- * This class defines a generic operation that may be processed by the
- * Directory Server. Specific subclasses should implement specific
- * functionality appropriate for the type of operation.
+ * This interface defines a generic operation that may be processed by
+ * the Directory Server. Specific subclasses should implement
+ * specific functionality appropriate for the type of operation.
* <BR><BR>
* Note that this class is not intended to be subclassed by any
* third-party code outside of the OpenDS project. It should only be
* extended by the operation types included in the
* {@code org.opends.server.core} package.
*/
-public abstract class Operation
- implements PreParseOperation, PreOperationOperation,
- PostOperationOperation, PostResponseOperation,
- Runnable
+public interface Operation
{
/**
- * The set of response controls that will always be returned for an
- * abandon operation.
+ * Identifier used to get the local operation [if any] in the
+ * attachments.
*/
- protected static final List<Control> NO_RESPONSE_CONTROLS =
- new ArrayList<Control>(0);
-
-
-
- /**
- * The client connection with which this operation is associated.
- */
- protected final ClientConnection clientConnection;
-
-
-
- /**
- * The message ID for this operation.
- */
- protected final int messageID;
-
-
-
- /**
- * The operation ID for this operation.
- */
- protected final long operationID;
-
-
-
- // Indicates whether this is an internal operation triggered within
- // the server itself rather than requested by an external client.
- private boolean isInternalOperation;
-
- // Indicates whether this operation is involved in data
- // synchronization processing.
- private boolean isSynchronizationOperation;
-
- // The cancel result for this operation.
- private CancelResult cancelResult;
-
- // The matched DN for this operation.
- private DN matchedDN;
-
- // The entry for the authorization identify for this operation.
- private Entry authorizationEntry;
-
- // A set of attachments associated with this operation that might be
- // used by various components during its processing.
- private Map<String,Object> attachments;
-
- // The set of controls included in the request from the client.
- private List<Control> requestControls;
-
- // The set of referral URLs for this operation.
- private List<String> referralURLs;
-
- // The result code for this operation.
- private ResultCode resultCode;
-
- // Additional information that should be included in the log but not
- // sent to the client.
- private StringBuilder additionalLogMessage;
-
- // The error message for this operation that should be included in
- // the log and in the response to the client.
- private StringBuilder errorMessage;
-
- // Indicates whether this operation nneds to be synchronized to
- // other copies of the data.
- private boolean dontSynchronizeFlag;
-
-
-
- /**
- * Creates a new operation with the provided information.
- *
- * @param clientConnection The client connection with which this
- * operation is associated.
- * @param operationID The identifier assigned to this
- * operation for the client connection.
- * @param messageID The message ID of the request with
- * which this operation is associated.
- * @param requestControls The set of controls included in the
- * request.
- */
- protected Operation(ClientConnection clientConnection,
- long operationID, int messageID,
- List<Control> requestControls)
- {
- this.clientConnection = clientConnection;
- this.operationID = operationID;
- this.messageID = messageID;
-
- if (requestControls == null)
- {
- this.requestControls = new ArrayList<Control>(0);
- }
- else
- {
- this.requestControls = requestControls;
- }
-
- resultCode = ResultCode.UNDEFINED;
- additionalLogMessage = new StringBuilder();
- errorMessage = new StringBuilder();
- attachments = new HashMap<String,Object>();
- matchedDN = null;
- referralURLs = null;
- cancelResult = null;
- isInternalOperation = false;
- isSynchronizationOperation = false;
- authorizationEntry =
- clientConnection.getAuthenticationInfo().
- getAuthorizationEntry();
- }
-
-
+ public static final String LOCALBACKENDOPERATIONS =
+ "LocalBackendOperations";
/**
* Retrieves the operation type for this operation.
@@ -186,8 +61,6 @@
*/
public abstract OperationType getOperationType();
-
-
/**
* Terminates the client connection being used to process this
* operation. If this is called by a plugin, then that plugin must
@@ -213,8 +86,6 @@
boolean sendNotification, String message,
int messageID);
-
-
/**
* Retrieves a set of standard elements that should be logged in all
* requests and responses for all types of operations. Each element
@@ -226,20 +97,7 @@
* @return A standard set of elements that should be logged in
* requests and responses for all types of operations.
*/
- public final String[][] getCommonLogElements()
- {
- return new String[][]
- {
- new String[] { LOG_ELEMENT_CONNECTION_ID,
- String.valueOf(getConnectionID()) },
- new String[] { LOG_ELEMENT_OPERATION_ID,
- String.valueOf(operationID) },
- new String[] { LOG_ELEMENT_MESSAGE_ID,
- String.valueOf(messageID) }
- };
- }
-
-
+ public abstract String[][] getCommonLogElements();
/**
* Retrieves a standard set of elements that should be logged in
@@ -254,8 +112,6 @@
*/
public abstract String[][] getRequestLogElements();
-
-
/**
* Retrieves a standard set of elements that should be logged in
* responses for this type of operation. Each element in the array
@@ -269,9 +125,6 @@
*/
public abstract String[][] getResponseLogElements();
-
-
-
/**
* Retrieves the client connection with which this operation is
* associated.
@@ -279,12 +132,7 @@
* @return The client connection with which this operation is
* associated.
*/
- public final ClientConnection getClientConnection()
- {
- return clientConnection;
- }
-
-
+ public abstract ClientConnection getClientConnection();
/**
* Retrieves the unique identifier that is assigned to the client
@@ -293,36 +141,21 @@
* @return The unique identifier that is assigned to the client
* connection that submitted this operation.
*/
- public final long getConnectionID()
- {
- return clientConnection.getConnectionID();
- }
-
-
+ public abstract long getConnectionID();
/**
* Retrieves the operation ID for this operation.
*
* @return The operation ID for this operation.
*/
- public final long getOperationID()
- {
- return operationID;
- }
-
-
+ public abstract long getOperationID();
/**
* Retrieves the message ID assigned to this operation.
*
* @return The message ID assigned to this operation.
*/
- public final int getMessageID()
- {
- return messageID;
- }
-
-
+ public abstract int getMessageID();
/**
* Retrieves the set of controls included in the request from the
@@ -331,12 +164,7 @@
* @return The set of controls included in the request from the
* client.
*/
- public final List<Control> getRequestControls()
- {
- return requestControls;
- }
-
-
+ public abstract List<Control> getRequestControls();
/**
* Adds the provided control to the set of request controls for this
@@ -345,12 +173,7 @@
* @param control The control to add to the set of request
* controls for this operation.
*/
- public final void addRequestControl(Control control)
- {
- requestControls.add(control);
- }
-
-
+ public abstract void addRequestControl(Control control);
/**
* Removes the provided control from the set of request controls for
@@ -360,12 +183,7 @@
* @param control The control to remove from the set of request
* controls for this operation.
*/
- public final void removeRequestControl(Control control)
- {
- requestControls.remove(control);
- }
-
-
+ public abstract void removeRequestControl(Control control);
/**
* Retrieves the set of controls to include in the response to the
@@ -376,8 +194,6 @@
*/
public abstract List<Control> getResponseControls();
-
-
/**
* Adds the provided control to the set of controls to include in
* the response to the client. This method may not be called by
@@ -388,8 +204,6 @@
*/
public abstract void addResponseControl(Control control);
-
-
/**
* Removes the provided control from the set of controls to include
* in the response to the client. This method may not be called by
@@ -400,8 +214,6 @@
*/
public abstract void removeResponseControl(Control control);
-
-
/**
* Retrieves the result code for this operation.
*
@@ -409,12 +221,7 @@
* {@code UNDEFINED} if the operation has not yet
* completed.
*/
- public final ResultCode getResultCode()
- {
- return resultCode;
- }
-
-
+ public abstract ResultCode getResultCode();
/**
* Specifies the result code for this operation. This method may
@@ -422,12 +229,7 @@
*
* @param resultCode The result code for this operation.
*/
- public final void setResultCode(ResultCode resultCode)
- {
- this.resultCode = resultCode;
- }
-
-
+ public abstract void setResultCode(ResultCode resultCode);
/**
* Retrieves the error message for this operation. Its contents may
@@ -436,12 +238,7 @@
*
* @return The error message for this operation.
*/
- public final StringBuilder getErrorMessage()
- {
- return errorMessage;
- }
-
-
+ public abstract StringBuilder getErrorMessage();
/**
* Specifies the error message for this operation. This method may
@@ -449,19 +246,7 @@
*
* @param errorMessage The error message for this operation.
*/
- public final void setErrorMessage(StringBuilder errorMessage)
- {
- if (errorMessage == null)
- {
- this.errorMessage = new StringBuilder();
- }
- else
- {
- this.errorMessage = errorMessage;
- }
- }
-
-
+ public abstract void setErrorMessage(StringBuilder errorMessage);
/**
* Appends the provided message to the error message buffer. If the
@@ -472,24 +257,7 @@
* @param message The message to append to the error message
* buffer.
*/
- public final void appendErrorMessage(String message)
- {
- if (errorMessage == null)
- {
- errorMessage = new StringBuilder(message);
- }
- else
- {
- if (errorMessage.length() > 0)
- {
- errorMessage.append(" ");
- }
-
- errorMessage.append(message);
- }
- }
-
-
+ public abstract void appendErrorMessage(String message);
/**
* Retrieves the additional log message for this operation, which
@@ -500,12 +268,7 @@
*
* @return The additional log message for this operation.
*/
- public final StringBuilder getAdditionalLogMessage()
- {
- return additionalLogMessage;
- }
-
-
+ public abstract StringBuilder getAdditionalLogMessage();
/**
* Specifies the additional log message for this operation, which
@@ -516,20 +279,8 @@
* @param additionalLogMessage The additional log message for this
* operation.
*/
- public final void setAdditionalLogMessage(StringBuilder
- additionalLogMessage)
- {
- if (additionalLogMessage == null)
- {
- this.additionalLogMessage = new StringBuilder();
- }
- else
- {
- this.additionalLogMessage = additionalLogMessage;
- }
- }
-
-
+ public abstract void setAdditionalLogMessage(
+ StringBuilder additionalLogMessage);
/**
* Appends the provided message to the additional log information
@@ -539,19 +290,7 @@
* @param message The message that should be appended to the
* additional log information for this operation.
*/
- public final void appendAdditionalLogMessage(String message)
- {
- if (additionalLogMessage == null)
- {
- additionalLogMessage = new StringBuilder(message);
- }
- else
- {
- additionalLogMessage.append(message);
- }
- }
-
-
+ public abstract void appendAdditionalLogMessage(String message);
/**
* Retrieves the matched DN for this operation.
@@ -560,12 +299,7 @@
* the operation has not yet completed or does not have a
* matched DN.
*/
- public final DN getMatchedDN()
- {
- return matchedDN;
- }
-
-
+ public abstract DN getMatchedDN();
/**
* Specifies the matched DN for this operation. This may not be
@@ -573,12 +307,7 @@
*
* @param matchedDN The matched DN for this operation.
*/
- public final void setMatchedDN(DN matchedDN)
- {
- this.matchedDN = matchedDN;
- }
-
-
+ public abstract void setMatchedDN(DN matchedDN);
/**
* Retrieves the set of referral URLs for this operation. Its
@@ -588,12 +317,7 @@
* {@code null} if the operation is not yet complete or
* does not have a set of referral URLs.
*/
- public final List<String> getReferralURLs()
- {
- return referralURLs;
- }
-
-
+ public abstract List<String> getReferralURLs();
/**
* Specifies the set of referral URLs for this operation. This may
@@ -602,12 +326,7 @@
* @param referralURLs The set of referral URLs for this
* operation.
*/
- public final void setReferralURLs(List<String> referralURLs)
- {
- this.referralURLs = referralURLs;
- }
-
-
+ public abstract void setReferralURLs(List<String> referralURLs);
/**
* Sets the response elements for this operation based on the
@@ -618,17 +337,8 @@
* information to use for the response
* elements.
*/
- public final void setResponseData(
- DirectoryException directoryException)
- {
- this.resultCode = directoryException.getResultCode();
- this.matchedDN = directoryException.getMatchedDN();
- this.referralURLs = directoryException.getReferralURLs();
-
- appendErrorMessage(directoryException.getErrorMessage());
- }
-
-
+ public abstract void setResponseData(
+ DirectoryException directoryException);
/**
* Indicates whether this is an internal operation rather than one
@@ -637,12 +347,7 @@
* @return {@code true} if this is an internal operation, or
* {@code false} if it is not.
*/
- public final boolean isInternalOperation()
- {
- return isInternalOperation;
- }
-
-
+ public abstract boolean isInternalOperation();
/**
* Specifies whether this is an internal operation rather than one
@@ -654,12 +359,8 @@
* that was requested by an external
* client.
*/
- public final void setInternalOperation(boolean isInternalOperation)
- {
- this.isInternalOperation = isInternalOperation;
- }
-
-
+ public abstract void setInternalOperation(boolean
+ isInternalOperation);
/**
* Indicates whether this is a synchronization operation rather than
@@ -668,12 +369,7 @@
* @return {@code true} if this is a data synchronization
* operation, or {@code false} if it is not.
*/
- public final boolean isSynchronizationOperation()
- {
- return isSynchronizationOperation;
- }
-
-
+ public abstract boolean isSynchronizationOperation();
/**
* Specifies whether this is a synchronization operation rather than
@@ -686,12 +382,8 @@
* requested by an external
* client.
*/
- public final void setSynchronizationOperation(
- boolean isSynchronizationOperation)
- {
- this.isSynchronizationOperation = isSynchronizationOperation;
- }
-
+ public abstract void setSynchronizationOperation(
+ boolean isSynchronizationOperation);
/**
* Specifies whether this operation must be synchronized to other
@@ -701,10 +393,7 @@
* synchronized to other copies
* of the data.
*/
- public final void setDontSynchronize(boolean dontSynchronize)
- {
- this.dontSynchronizeFlag = dontSynchronize;
- }
+ public abstract void setDontSynchronize(boolean dontSynchronize);
/**
* Retrieves the entry for the user that should be considered the
@@ -722,12 +411,7 @@
* {@code null} if the authorization identity should be the
* unauthenticated user.
*/
- public final Entry getAuthorizationEntry()
- {
- return authorizationEntry;
- }
-
-
+ public abstract Entry getAuthorizationEntry();
/**
* Provides the entry for the user that should be considered the
@@ -740,12 +424,8 @@
* if it should be the unauthenticated
* user.
*/
- public final void setAuthorizationEntry(Entry authorizationEntry)
- {
- this.authorizationEntry = authorizationEntry;
- }
-
-
+ public abstract void setAuthorizationEntry(Entry
+ authorizationEntry);
/**
* Retrieves the authorization DN for this operation. In many
@@ -760,19 +440,7 @@
* @return The authorization DN for this operation, or the null DN
* if it should be the unauthenticated user..
*/
- public final DN getAuthorizationDN()
- {
- if (authorizationEntry == null)
- {
- return DN.nullDN();
- }
- else
- {
- return authorizationEntry.getDN();
- }
- }
-
-
+ public abstract DN getAuthorizationDN();
/**
* Retrieves the set of attachments defined for this operation, as a
@@ -780,12 +448,7 @@
*
* @return The set of attachments defined for this operation.
*/
- public final Map<String,Object> getAttachments()
- {
- return attachments;
- }
-
-
+ public abstract Map<String, Object> getAttachments();
/**
* Retrieves the attachment with the specified name.
@@ -796,12 +459,7 @@
* @return The requested attachment object, or {@code null} if it
* does not exist.
*/
- public final Object getAttachment(String name)
- {
- return attachments.get(name);
- }
-
-
+ public abstract Object getAttachment(String name);
/**
* Removes the attachment with the specified name.
@@ -812,12 +470,7 @@
* @return The attachment that was removed, or {@code null} if it
* does not exist.
*/
- public final Object removeAttachment(String name)
- {
- return attachments.remove(name);
- }
-
-
+ public abstract Object removeAttachment(String name);
/**
* Sets the value of the specified attachment. If an attachment
@@ -831,12 +484,7 @@
* name, or {@code null} if there was previously no such
* attachment.
*/
- public final Object setAttachment(String name, Object value)
- {
- return attachments.put(name, value);
- }
-
-
+ public abstract Object setAttachment(String name, Object value);
/**
* Retrieves the time that processing started for this operation.
@@ -845,8 +493,6 @@
*/
public abstract long getProcessingStartTime();
-
-
/**
* Retrieves the time that processing stopped for this operation.
* This will actually hold a time immediately before the response
@@ -856,8 +502,6 @@
*/
public abstract long getProcessingStopTime();
-
-
/**
* Retrieves the length of time in milliseconds that the server
* spent processing this operation. This should not be called until
@@ -868,32 +512,12 @@
*/
public abstract long getProcessingTime();
-
-
- /**
- * Performs the work of actually processing this operation. This
- * should include all processing for the operation, including
- * invoking plugins, logging messages, performing access control,
- * managing synchronization, and any other work that might need to
- * be done in the course of processing.
- */
- public abstract void run();
-
-
-
/**
* Indicates that processing on this operation has completed
* successfully and that the client should perform any associated
* cleanup work.
*/
- public final void operationCompleted()
- {
- // Notify the client connection that this operation is complete
- // and that it no longer needs to be retained.
- clientConnection.removeOperationInProgress(messageID);
- }
-
-
+ public abstract void operationCompleted();
/**
* Attempts to cancel this operation before processing has
@@ -907,8 +531,6 @@
*/
public abstract CancelResult cancel(CancelRequest cancelRequest);
-
-
/**
* Sets the cancel request for this operation, if applicable. This
* should only be used for testing purposes (e.g., for ensuring a
@@ -923,10 +545,8 @@
* {@code false} if it was not for some reason (e.g., the
* specified operation cannot be cancelled).
*/
- protected abstract boolean setCancelRequest(CancelRequest
- cancelRequest);
-
-
+ public abstract boolean setCancelRequest(CancelRequest
+ cancelRequest);
/**
* Retrieves the cancel request that has been issued for this
@@ -939,8 +559,6 @@
*/
public abstract CancelRequest getCancelRequest();
-
-
/**
* Retrieves the cancel result for this operation.
*
@@ -948,24 +566,14 @@
* {@code null} if the operation has not seen and reacted
* to a cancel request.
*/
- public final CancelResult getCancelResult()
- {
- return cancelResult;
- }
-
-
+ public abstract CancelResult getCancelResult();
/**
* Specifies the cancel result for this operation.
*
* @param cancelResult The cancel result for this operation.
*/
- public final void setCancelResult(CancelResult cancelResult)
- {
- this.cancelResult = cancelResult;
- }
-
-
+ public abstract void setCancelResult(CancelResult cancelResult);
/**
* Indicates that this operation has been cancelled. If
@@ -976,40 +584,14 @@
*
* @param cancelRequest The request to cancel this operation.
*/
- protected final void indicateCancelled(CancelRequest cancelRequest)
- {
- setCancelResult(CancelResult.CANCELED);
-
- if (cancelRequest.notifyOriginalRequestor() ||
- DirectoryServer.notifyAbandonedOperations())
- {
- setResultCode(ResultCode.CANCELED);
-
- String cancelReason = cancelRequest.getCancelReason();
- if (cancelReason != null)
- {
- appendErrorMessage(cancelReason);
- }
-
- clientConnection.sendResponse(this);
- }
- }
-
-
+ public abstract void indicateCancelled(CancelRequest cancelRequest);
/**
* Retrieves a string representation of this operation.
*
* @return A string representation of this operation.
*/
- public final String toString()
- {
- StringBuilder buffer = new StringBuilder();
- toString(buffer);
- return buffer.toString();
- }
-
-
+ public abstract String toString();
/**
* Appends a string representation of this operation to the provided
@@ -1020,8 +602,6 @@
*/
public abstract void toString(StringBuilder buffer);
-
-
/**
* Indicates whether this operation needs to be synchronized to
* other copies of the data.
@@ -1030,9 +610,28 @@
* synchronized, or
* <CODE>false</CODE> if it needs to be synchronized.
*/
- public boolean dontSynchronize()
- {
- return dontSynchronizeFlag;
- }
+ public abstract boolean dontSynchronize();
+
+ /**
+ * Set the time at which the processing stopped for this operation.
+ * This will actually hold a time immediately before the response
+ * was sent to the client.
+ */
+ public abstract void setProcessingStopTime();
+
+ /**
+ * Set the time at which the processing started for this operation.
+ */
+ public abstract void setProcessingStartTime();
+
+ /**
+ * Set the attachments to the operation.
+ *
+ * @param attachments - Attachments to register within the
+ * operation
+ */
+ public abstract void setAttachments(Map<String,
+ Object> attachments);
+
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/LeafWorkflowElement.java b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/LeafWorkflowElement.java
new file mode 100644
index 0000000..098e06d
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/LeafWorkflowElement.java
@@ -0,0 +1,40 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.workflowelement;
+
+
+
+/**
+ * This class gathers all the workflow elements that are encapsulating
+ * physical repositories such as local database, remote LDAP servers,
+ * JDBC repository or LDIF flat file.
+ */
+public abstract class LeafWorkflowElement
+ extends WorkflowElement
+{
+ // Empty at the moment.
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/WorkflowElement.java b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/WorkflowElement.java
new file mode 100644
index 0000000..df604c3
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/WorkflowElement.java
@@ -0,0 +1,81 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.workflowelement;
+
+import org.opends.server.types.Operation;
+
+
+/**
+ * This class defines the super class for all the workflow elements. A workflow
+ * element is a task in a workflow. A workflow element can wrap a physical
+ * repository such as a local backend, a remote LDAP server or a local ldif
+ * file. A workflow element can also be used to route operations. This is the
+ * case for load balancing and distribution. And workflow element can be used
+ * in a virtual environment to transform data (DN and attribute renaming,
+ * attribute value renaming...).
+ */
+public abstract class WorkflowElement
+{
+
+ /**
+ * Indicates whether the workflow element encapsulates a private
+ * local backend.
+ */
+ protected boolean isPrivate = false;
+
+
+ /**
+ * Creates a new instance of the workflow element.
+ */
+ public WorkflowElement()
+ {
+ // No implementation is required.
+ }
+
+
+ /**
+ * Executes the workflow element for an operation.
+ *
+ * @param operation the operation to execute
+ */
+ public abstract void execute(
+ Operation operation
+ );
+
+
+ /**
+ * Indicates whether the workflow element encapsulates a private
+ * local backend.
+ *
+ * @return <code>true</code> if the workflow element encapsulates a private
+ * local backend, <code>false</code> otherwise
+ */
+ public boolean isPrivate()
+ {
+ return isPrivate;
+ }
+}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
index d74112b..7e50734 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
@@ -69,13 +69,13 @@
import org.opends.server.protocols.ldap.BindResponseProtocolOp;
import org.opends.server.tools.LDAPModify;
import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
import org.opends.server.types.FilePermission;
import org.opends.server.types.InitializationException;
import org.opends.server.types.OperatingSystem;
import org.opends.server.types.ResultCode;
import static org.testng.Assert.*;
-import static org.testng.Assert.assertEquals;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
@@ -151,7 +151,8 @@
* configuration.
*/
public static void startServer()
- throws IOException, InitializationException, ConfigException
+ throws IOException, InitializationException, ConfigException,
+ DirectoryException
{
if (SERVER_STARTED)
{
@@ -352,6 +353,8 @@
assertTrue(InvocationCounterPlugin.startupCalled());
SERVER_STARTED = true;
+
+ initializeTestBackend(true);
}
/**
@@ -439,7 +442,8 @@
* @throws Exception If an unexpected problem occurs.
*/
public static void initializeTestBackend(boolean createBaseEntry)
- throws Exception
+ throws IOException, InitializationException, ConfigException,
+ DirectoryException
{
startServer();
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
index ad41d50..fa3e3bf 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
@@ -35,10 +35,10 @@
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
-import org.opends.server.admin.std.server.SchemaBackendCfg;
+import org.opends.server.backends.SchemaBackend;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.AddOperationBasis;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.SchemaConfigManager;
@@ -264,8 +264,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- AddOperation addOperation =
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
@@ -287,8 +287,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- DeleteOperation deleteOperation =
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ DeleteOperationBasis deleteOperation =
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, schemaDN);
schemaBackend.deleteEntry(schemaDN, deleteOperation);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
index e511c2a..a409d28 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
@@ -54,6 +54,10 @@
import static org.testng.Assert.assertEquals;
import com.sleepycat.je.DatabaseEntry;
+import org.opends.server.core.DeleteOperationBasis;
+import org.opends.server.core.ModifyOperationBasis;
+import org.opends.server.workflowelement.localbackend.LocalBackendModifyOperation;
+
/**
* BackendImpl Tester.
*/
@@ -726,7 +730,7 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- DeleteOperation delete = new DeleteOperation(conn,
+ DeleteOperationBasis delete = new DeleteOperationBasis(conn,
conn.nextOperationID(),
conn.nextMessageID(),
deleteSubTreeControl,
@@ -777,10 +781,10 @@
entryID = ec.getDN2ID().get(null,
DN.decode("uid=user.539,ou=People,dc=test,dc=com"));
- DeleteOperation delete = new DeleteOperation(conn,
- conn.nextOperationID(),
- conn.nextMessageID(),
- noControls,
+ DeleteOperationBasis delete = new DeleteOperationBasis(conn,
+ conn.nextOperationID(),
+ conn.nextMessageID(),
+ noControls,
DN.decode("uid=user.539,ou=People,dc=test,dc=com"));
@@ -1025,15 +1029,15 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOp = new ModifyOperation(conn,
- conn.nextOperationID(),
- conn.nextMessageID(),
- noControls,
- DN.decode("uid=user.1,ou=People,dc=test,dc=com"),
- modifications);
+ ModifyOperationBasis modifyOp = new ModifyOperationBasis(conn,
+ conn.nextOperationID(),
+ conn.nextMessageID(),
+ noControls,
+ DN.decode("uid=user.1,ou=People,dc=test,dc=com"),
+ modifications);
- backend.replaceEntry(newEntry, modifyOp);
+ backend.replaceEntry(newEntry, modifyOp);
entry = ec.getEntry(DN.decode("uid=user.1,ou=People,dc=test,dc=com"));
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ServerSideSortControlTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ServerSideSortControlTestCase.java
index 82da9bc..388750e 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ServerSideSortControlTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/ServerSideSortControlTestCase.java
@@ -28,14 +28,13 @@
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.ArrayList;
+import java.util.List;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
@@ -43,19 +42,16 @@
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.types.AttributeType;
import org.opends.server.types.Control;
-import org.opends.server.types.DereferencePolicy;
-import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
+import org.opends.server.types.DereferencePolicy;
import org.opends.server.types.Entry;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchScope;
import org.opends.server.types.SortKey;
import org.opends.server.types.SortOrder;
-
-import static org.testng.Assert.*;
-
-import static org.opends.server.util.ServerConstants.*;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
@@ -327,6 +323,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -389,6 +386,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -449,6 +447,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -511,6 +510,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -571,6 +571,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -631,6 +632,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -691,6 +693,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertFalse(internalSearch.getResultCode() == ResultCode.SUCCESS);
}
@@ -723,6 +726,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertFalse(internalSearch.getResultCode() == ResultCode.SUCCESS);
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/VLVControlTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/VLVControlTestCase.java
index 9b63163..abe7e45 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/VLVControlTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/controls/VLVControlTestCase.java
@@ -28,14 +28,15 @@
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
+import static org.opends.server.util.ServerConstants.OID_SERVER_SIDE_SORT_RESPONSE_CONTROL;
+import static org.opends.server.util.ServerConstants.OID_VLV_RESPONSE_CONTROL;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.fail;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.ArrayList;
+import java.util.List;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
@@ -45,19 +46,14 @@
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.types.AttributeType;
import org.opends.server.types.Control;
-import org.opends.server.types.DereferencePolicy;
-import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
+import org.opends.server.types.DereferencePolicy;
import org.opends.server.types.Entry;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchScope;
-import org.opends.server.types.SortKey;
-import org.opends.server.types.SortOrder;
-
-import static org.testng.Assert.*;
-
-import static org.opends.server.util.ServerConstants.*;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
@@ -497,6 +493,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -574,6 +571,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -650,6 +648,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
// It will be successful because it's not a critical control.
@@ -700,6 +699,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
// It will be successful because it's not a critical control.
@@ -751,6 +751,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -827,6 +828,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -905,6 +907,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -983,6 +986,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -1061,6 +1065,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
assertEquals(internalSearch.getResultCode(), ResultCode.SUCCESS);
@@ -1139,6 +1144,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
SearchFilter.createFilterFromString("(objectClass=person)"),
null, null);
+
internalSearch.run();
// It will be successful because the control isn't critical.
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AbandonOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AbandonOperationTestCase.java
index 55fc9b7..efa7e1f 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AbandonOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AbandonOperationTestCase.java
@@ -28,21 +28,22 @@
+import static org.opends.server.util.ServerConstants.OID_WHO_AM_I_REQUEST;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
import java.net.Socket;
import java.util.ArrayList;
import java.util.LinkedHashSet;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
import org.opends.server.TestCaseUtils;
import org.opends.server.plugins.DelayPreOpPlugin;
import org.opends.server.plugins.DisconnectClientPlugin;
import org.opends.server.plugins.InvocationCounterPlugin;
-import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.asn1.ASN1Reader;
-import org.opends.server.protocols.asn1.ASN1Sequence;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.ldap.AbandonRequestProtocolOp;
@@ -61,10 +62,10 @@
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.LDAPModification;
import org.opends.server.protocols.ldap.LDAPResultCode;
-import org.opends.server.protocols.ldap.ModifyRequestProtocolOp;
-import org.opends.server.protocols.ldap.ModifyResponseProtocolOp;
import org.opends.server.protocols.ldap.ModifyDNRequestProtocolOp;
import org.opends.server.protocols.ldap.ModifyDNResponseProtocolOp;
+import org.opends.server.protocols.ldap.ModifyRequestProtocolOp;
+import org.opends.server.protocols.ldap.ModifyResponseProtocolOp;
import org.opends.server.protocols.ldap.SearchRequestProtocolOp;
import org.opends.server.protocols.ldap.SearchResultDoneProtocolOp;
import org.opends.server.types.CancelRequest;
@@ -78,10 +79,7 @@
import org.opends.server.types.RawModification;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchScope;
-
-import static org.testng.Assert.*;
-
-import static org.opends.server.util.ServerConstants.*;
+import org.testng.annotations.Test;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java
index 770ee7d..b7e6bef 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/AddOperationTestCase.java
@@ -128,17 +128,17 @@
Operation[] opArray = new Operation[]
{
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, new ASN1OctetString("ou=People,o=test"),
ldapAttrList),
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, new ASN1OctetString("ou=People,o=test"),
ldapAttrList),
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes()),
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes()),
@@ -182,7 +182,7 @@
* @param addOperation The add operation to be tested.
*/
@Test(dataProvider = "addOperations")
- public void testGetAndSetRawEntryDN(AddOperation addOperation)
+ public void testGetAndSetRawEntryDN(AddOperationBasis addOperation)
{
ByteString originalDN = addOperation.getRawEntryDN();
assertNotNull(originalDN);
@@ -201,7 +201,7 @@
/**
* Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
- * the DN to be initially null.
+ * the rawEntryDN to be decoded.
*/
@Test()
public void testGetEntryDNInitiallyNull()
@@ -220,11 +220,11 @@
values.add(new ASN1OctetString("People"));
ldapAttrList.add(new LDAPAttribute("ou", values));
- AddOperation addOperation =
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, new ASN1OctetString("ou=People,o=test"),
ldapAttrList);
- assertNull(addOperation.getEntryDN());
+ assertNotNull(addOperation.getEntryDN());
}
@@ -248,8 +248,8 @@
"objectClass: organizationalUnit",
"ou: People");
- AddOperation addOperation =
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
@@ -261,7 +261,7 @@
/**
* Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
* the DN to be initially non-null but then becomes null after the raw DN is
- * changed.
+ * changed, and <CODE>getEntryDN</CODE> method recomputes it again
*
* @throws Exception If an unexpected problem occurs.
*/
@@ -278,15 +278,15 @@
"objectClass: organizationalUnit",
"ou: People");
- AddOperation addOperation =
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
assertNotNull(addOperation.getEntryDN());
addOperation.setRawEntryDN(new ASN1OctetString("ou=Users,o=test"));
- assertNull(addOperation.getEntryDN());
+ assertNotNull(addOperation.getEntryDN());
}
@@ -298,7 +298,7 @@
* @param addOperation The add operation to be tested.
*/
@Test(dataProvider = "addOperations")
- public void testGetAndSetRawAttributes(AddOperation addOperation)
+ public void testGetAndSetRawAttributes(AddOperationBasis addOperation)
{
List<RawAttribute> rawAttrs = addOperation.getRawAttributes();
assertNotNull(rawAttrs);
@@ -579,7 +579,6 @@
*/
private void retrieveCompletedOperationElements(AddOperation addOperation)
{
- assertNotNull(addOperation.getEntryToAdd());
assertTrue(addOperation.getProcessingStartTime() > 0);
assertTrue(addOperation.getProcessingStopTime() >=
addOperation.getProcessingStartTime());
@@ -1984,8 +1983,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- AddOperation addOperation =
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(),
entry.getOperationalAttributes());
@@ -2517,8 +2516,8 @@
rawAttrs.add(RawAttribute.create("objectClass", ocValues));
rawAttrs.add(RawAttribute.create("o", "test"));
- AddOperation addOperation =
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, new ASN1OctetString("o=test"), rawAttrs);
addOperation.run();
assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java
index 2c0d57f..b9a23ba 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java
@@ -37,9 +37,7 @@
import org.testng.annotations.BeforeMethod;
import org.opends.server.TestCaseUtils;
-import org.opends.server.core.AddOperation;
import org.opends.server.core.BindOperation;
-import org.opends.server.core.ModifyOperation;
import org.opends.server.plugins.DisconnectClientPlugin;
import org.opends.server.plugins.InvocationCounterPlugin;
import org.opends.server.plugins.ShortCircuitPlugin;
@@ -97,45 +95,45 @@
BindOperation[] simpleBinds = new BindOperation[]
{
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", new ASN1OctetString(),
new ASN1OctetString()),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", new ASN1OctetString(),
new ASN1OctetString()),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", nullOS, new ASN1OctetString()),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", nullOS, new ASN1OctetString()),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", new ASN1OctetString(), nullOS),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", new ASN1OctetString(), nullOS),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", nullOS, nullOS),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", nullOS, nullOS),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3",
new ASN1OctetString("cn=Directory Manager"),
new ASN1OctetString("password")),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", DN.nullDN(), new ASN1OctetString()),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", DN.nullDN(), new ASN1OctetString()),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", nullDN, new ASN1OctetString()),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", nullDN, new ASN1OctetString()),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", DN.nullDN(), nullOS),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", DN.nullDN(), nullOS),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", nullDN, nullOS),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", nullDN, nullOS),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", DN.decode("cn=Directory Manager"),
new ASN1OctetString("password"))
};
@@ -170,45 +168,45 @@
BindOperation[] saslBinds = new BindOperation[]
{
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", new ASN1OctetString(), "EXTERNAL", null),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", new ASN1OctetString(), "EXTERNAL",
null),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", nullOS, "EXTERNAL", null),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", nullOS, "EXTERNAL", null),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", new ASN1OctetString(), "PLAIN",
new ASN1OctetString("\u0000u:test.user\u0000password")),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", new ASN1OctetString(), "PLAIN",
new ASN1OctetString("\u0000u:test.user\u0000password")),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", nullOS, "PLAIN",
new ASN1OctetString("\u0000u:test.user\u0000password")),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", nullOS, "PLAIN",
new ASN1OctetString("\u0000u:test.user\u0000password")),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", DN.nullDN(), "EXTERNAL", null),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", DN.nullDN(), "EXTERNAL", null),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", nullDN, "EXTERNAL", null),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", nullDN, "EXTERNAL", null),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", DN.nullDN(), "PLAIN",
new ASN1OctetString("\u0000u:test.user\u0000password")),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", DN.nullDN(), "PLAIN",
new ASN1OctetString("\u0000u:test.user\u0000password")),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, "3", nullDN, "PLAIN",
new ASN1OctetString("\u0000u:test.user\u0000password")),
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
noControls, "3", nullDN, "PLAIN",
new ASN1OctetString("\u0000u:test.user\u0000password"))
};
@@ -1670,8 +1668,8 @@
ArrayList<Control> requestControls = new ArrayList<Control>(1);
requestControls.add(new Control("1.2.3.4", true));
- BindOperation bindOperation =
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
requestControls, "3", DN.nullDN(),
new ASN1OctetString());
bindOperation.run();
@@ -1697,8 +1695,8 @@
ASN1OctetString saslCreds =
new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
- BindOperation bindOperation =
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
requestControls, "3", DN.nullDN(), "PLAIN",
saslCreds);
bindOperation.run();
@@ -1721,10 +1719,11 @@
ArrayList<Control> requestControls = new ArrayList<Control>(1);
requestControls.add(new Control("1.2.3.4", false));
- BindOperation bindOperation =
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
requestControls, "3", DN.nullDN(),
new ASN1OctetString());
+
bindOperation.run();
assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
}
@@ -1747,8 +1746,8 @@
ASN1OctetString saslCreds =
new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
- BindOperation bindOperation =
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
requestControls, "3", DN.nullDN(), "PLAIN",
saslCreds);
bindOperation.run();
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java
index 71426a8..4d9037b 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/DeleteOperationTestCase.java
@@ -33,7 +33,6 @@
import java.util.List;
import java.util.concurrent.locks.Lock;
-import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.testng.annotations.AfterMethod;
@@ -44,13 +43,11 @@
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.asn1.ASN1Reader;
-import org.opends.server.protocols.asn1.ASN1Sequence;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.ldap.BindRequestProtocolOp;
import org.opends.server.protocols.ldap.BindResponseProtocolOp;
import org.opends.server.protocols.ldap.DeleteRequestProtocolOp;
-import org.opends.server.protocols.ldap.DeleteResponseProtocolOp;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.tools.LDAPDelete;
import org.opends.server.types.ByteString;
@@ -63,6 +60,7 @@
import org.opends.server.types.ResultCode;
import org.opends.server.types.WritabilityMode;
import org.opends.server.types.DirectoryException;
+import org.opends.server.workflowelement.localbackend.LocalBackendDeleteOperation;
import static org.testng.Assert.*;
@@ -95,22 +93,22 @@
return new Operation[]
{
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(), new ASN1OctetString()),
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, new ASN1OctetString()),
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(),
new ASN1OctetString("o=test")),
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, new ASN1OctetString("o=test")),
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(), DN.nullDN()),
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, DN.nullDN()),
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(), DN.decode("o=test")),
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, DN.decode("o=test"))
};
}
@@ -140,7 +138,8 @@
/**
- * Tests the <CODE>getEntryDN</CODE> method when it should be null.
+ * Tests the <CODE>getEntryDN</CODE> method that should decode the rawEntryDN
+ * to compute the entryDN.
*/
@Test()
public void testGetEntryDNNull()
@@ -149,9 +148,9 @@
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, new ASN1OctetString("o=test"));
- assertNull(deleteOperation.getEntryDN());
+ assertNotNull(deleteOperation.getEntryDN());
}
@@ -169,7 +168,7 @@
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, DN.decode("o=test"));
assertNotNull(deleteOperation.getEntryDN());
}
@@ -178,7 +177,10 @@
/**
* Tests the <CODE>getEntryDN</CODE> method when it originally started as
- * non-null but then was changed to null.
+ * non-null, then was changed to null; because of the call to the
+ * <CODE>setRawEntry<CODE> method, and becomes non-null again because
+ * of the call to the <CODE>getEntryDN</CODE> again.
+ *
*
* @throws Exception If an unexpected problem occurs.
*/
@@ -190,12 +192,12 @@
InternalClientConnection.getRootConnection();
DeleteOperation deleteOperation =
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, DN.decode("o=test"));
assertNotNull(deleteOperation.getEntryDN());
deleteOperation.setRawEntryDN(new ASN1OctetString("dc=example,dc=com"));
- assertNull(deleteOperation.getEntryDN());
+ assertNotNull(deleteOperation.getEntryDN());
}
@@ -208,7 +210,6 @@
DeleteOperation deleteOperation)
throws Exception
{
- assertNotNull(deleteOperation.getEntryToDelete());
assertTrue(deleteOperation.getProcessingStartTime() > 0);
assertTrue(deleteOperation.getProcessingStopTime() >=
deleteOperation.getProcessingStartTime());
@@ -241,8 +242,13 @@
conn.processDelete(new ASN1OctetString("o=test"));
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
retrieveCompletedOperationElements(deleteOperation);
-
- assertNotNull(deleteOperation.getEntryToDelete());
+ List localOps =
+ (List) (deleteOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS));
+ assertNotNull(localOps);
+ for (Object localOp : localOps){
+ LocalBackendDeleteOperation curOp = (LocalBackendDeleteOperation) localOp;
+ assertNotNull(curOp.getEntryToDelete());
+ }
}
@@ -265,7 +271,13 @@
DeleteOperation deleteOperation =
conn.processDelete(new ASN1OctetString("ou=People,o=test"));
assertFalse(deleteOperation.getResultCode() == ResultCode.SUCCESS);
- assertNull(deleteOperation.getEntryToDelete());
+ List localOps =
+ (List) (deleteOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS));
+ assertNotNull(localOps);
+ for (Object localOp : localOps){
+ LocalBackendDeleteOperation curOp = (LocalBackendDeleteOperation) localOp;
+ assertNull(curOp.getEntryToDelete());
+ }
}
@@ -795,8 +807,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- DeleteOperation deleteOperation =
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ DeleteOperationBasis deleteOperation =
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, new ASN1OctetString("o=test"));
CancelRequest cancelRequest = new CancelRequest(false,
@@ -1152,8 +1164,8 @@
List<Control> controls =
ShortCircuitPlugin.createShortCircuitControlList(0, "PreParse");
- DeleteOperation deleteOperation =
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ DeleteOperationBasis deleteOperation =
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, new ASN1OctetString("o=test"));
deleteOperation.run();
assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java
index 61be52b..5fb6a1c 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/ModifyOperationTestCase.java
@@ -31,6 +31,7 @@
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.locks.Lock;
import org.testng.annotations.DataProvider;
@@ -58,9 +59,9 @@
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.tools.LDAPModify;
import org.opends.server.types.*;
+import org.opends.server.workflowelement.localbackend.LocalBackendModifyOperation;
import static org.testng.Assert.*;
-import static org.testng.Assert.assertEquals;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
@@ -109,48 +110,48 @@
LDAPAttribute ldapAttr = new LDAPAttribute("description", ldapValues);
ldapMods.add(new LDAPModification(ModificationType.ADD, ldapAttr));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString("o=test"), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString("o=test"), ldapMods));
ldapMods = new ArrayList<RawModification>();
ldapMods.add(new LDAPModification(ModificationType.DELETE, ldapAttr));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString("o=test"), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString("o=test"), ldapMods));
ldapMods = new ArrayList<RawModification>();
ldapMods.add(new LDAPModification(ModificationType.REPLACE, ldapAttr));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString("o=test"), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString("o=test"), ldapMods));
@@ -161,16 +162,16 @@
ldapMods.add(new LDAPModification(ModificationType.DELETE, ldapAttr));
ldapMods.add(new LDAPModification(ModificationType.ADD, ldapAttr2));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString("o=test"), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString("o=test"), ldapMods));
@@ -179,16 +180,16 @@
ldapMods.add(new LDAPModification(ModificationType.REPLACE, ldapAttr));
ldapMods.add(new LDAPModification(ModificationType.REPLACE, ldapAttr2));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString(), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
new ASN1OctetString("o=test"), ldapMods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
new ASN1OctetString("o=test"), ldapMods));
@@ -198,15 +199,15 @@
mods.add(new Modification(ModificationType.ADD,
new Attribute("description", "foo")));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null, DN.nullDN(), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls, DN.nullDN(),
mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
DN.decode("o=test"), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
DN.decode("o=test"), mods));
@@ -214,15 +215,15 @@
mods.add(new Modification(ModificationType.DELETE,
new Attribute("description", "foo")));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null, DN.nullDN(), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls, DN.nullDN(),
mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
DN.decode("o=test"), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
DN.decode("o=test"), mods));
@@ -230,15 +231,15 @@
mods.add(new Modification(ModificationType.REPLACE,
new Attribute("description", "foo")));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null, DN.nullDN(), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls, DN.nullDN(),
mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
DN.decode("o=test"), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
DN.decode("o=test"), mods));
@@ -248,15 +249,15 @@
mods.add(new Modification(ModificationType.ADD,
new Attribute("description", "bar")));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null, DN.nullDN(), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls, DN.nullDN(),
mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
DN.decode("o=test"), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
DN.decode("o=test"), mods));
@@ -266,15 +267,15 @@
mods.add(new Modification(ModificationType.REPLACE,
new Attribute("cn", "bar")));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null, DN.nullDN(), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls, DN.nullDN(),
mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), null,
DN.decode("o=test"), mods));
- opList.add(new ModifyOperation(conn, conn.nextOperationID(),
+ opList.add(new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), noControls,
DN.decode("o=test"), mods));
@@ -349,8 +350,8 @@
/**
- * Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
- * the DN to be initially null.
+ * Tests the <CODE>getEntryDN</CODE> method that should decode
+ * the raw entry dn and return a non-null DN.
*/
@Test()
public void testGetEntryDNInitiallyNull()
@@ -366,9 +367,9 @@
mods.add(new LDAPModification(ModificationType.REPLACE, attr));
ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, new ASN1OctetString(), mods);
- assertNull(modifyOperation.getEntryDN());
+ assertNotNull(modifyOperation.getEntryDN());
}
@@ -390,7 +391,7 @@
mods.add(new Modification(ModificationType.REPLACE,
new Attribute("description", "foo")));
ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, DN.nullDN(), mods);
assertNotNull(modifyOperation.getEntryDN());
}
@@ -399,8 +400,8 @@
/**
* Tests the <CODE>getEntryDN</CODE> method for the case in which we expect
- * the DN to be initially non-null but then becomes null after the raw DN is
- * changed.
+ * the DN to be initially non-null, then is null after the raw DN is
+ * changed, but becomes non-null after the call to <CODE>getEntryDN</CODE>.
*
* @throws Exception If an unexpected problem occurs.
*/
@@ -415,12 +416,12 @@
mods.add(new Modification(ModificationType.REPLACE,
new Attribute("description", "foo")));
ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, DN.nullDN(), mods);
assertNotNull(modifyOperation.getEntryDN());
modifyOperation.setRawEntryDN(new ASN1OctetString("ou=Users,o=test"));
- assertNull(modifyOperation.getEntryDN());
+ assertNotNull(modifyOperation.getEntryDN());
}
@@ -468,16 +469,22 @@
private void retrieveSuccessfulOperationElements(
ModifyOperation modifyOperation)
{
- assertNotNull(modifyOperation.getCurrentEntry());
- assertNotNull(modifyOperation.getModifiedEntry());
assertTrue(modifyOperation.getProcessingStartTime() > 0);
assertTrue(modifyOperation.getProcessingStopTime() >=
modifyOperation.getProcessingStartTime());
assertTrue(modifyOperation.getProcessingTime() >= 0);
assertNotNull(modifyOperation.getResponseLogElements());
- modifyOperation.getNewPasswords();
- modifyOperation.getCurrentPasswords();
+ List localOps =
+ (List) (modifyOperation.getAttachment(Operation.LOCALBACKENDOPERATIONS));
+ assertNotNull(localOps);
+ for (Object localOp : localOps){
+ LocalBackendModifyOperation curOp = (LocalBackendModifyOperation) localOp;
+ curOp.getNewPasswords();
+ curOp.getCurrentPasswords();
+ assertNotNull(curOp.getCurrentEntry());
+ assertNotNull(curOp.getModifiedEntry());
+ }
long changeNumber = modifyOperation.getChangeNumber();
modifyOperation.setChangeNumber(changeNumber);
@@ -501,11 +508,6 @@
assertTrue(modifyOperation.getProcessingTime() >= 0);
assertNotNull(modifyOperation.getResponseLogElements());
- modifyOperation.getCurrentEntry();
- modifyOperation.getModifiedEntry();
- modifyOperation.getNewPasswords();
- modifyOperation.getCurrentPasswords();
-
long changeNumber = modifyOperation.getChangeNumber();
modifyOperation.setChangeNumber(changeNumber);
}
@@ -2014,7 +2016,7 @@
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
- new ASN1OctetString(baseDN),
+ new ASN1OctetString("uid=test.user," + baseDN),
SearchScope.WHOLE_SUBTREE,
DereferencePolicy.NEVER_DEREF_ALIASES,
Integer.MAX_VALUE,
@@ -4075,8 +4077,8 @@
ArrayList<RawModification> mods = new ArrayList<RawModification>();
mods.add(new LDAPModification(ModificationType.REPLACE, attr));
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
null, new ASN1OctetString(baseDN), mods);
CancelRequest cancelRequest = new CancelRequest(false,
@@ -4528,8 +4530,8 @@
mods.add(RawModification.create(ModificationType.REPLACE, "description",
"foo"));
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, new ASN1OctetString("o=test"), mods);
modifyOperation.run();
assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/NetworkGroupTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/NetworkGroupTest.java
new file mode 100644
index 0000000..9819e76
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/NetworkGroupTest.java
@@ -0,0 +1,470 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.workflowelement.WorkflowElement;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+/**
+ * This set of tests checks that network groups are properly created.
+ */
+public class NetworkGroupTest
+{
+ //===========================================================================
+ //
+ // B E F O R E C L A S S
+ //
+ //===========================================================================
+
+ /**
+ * Sets up the environment for performing the tests in this suite.
+ *
+ * @throws Exception if the environment could not be set up.
+ */
+ @BeforeClass
+ public void setUp()
+ throws Exception
+ {
+ // This test suite depends on having the schema available,
+ // so we'll start the server.
+ TestCaseUtils.startServer();
+ }
+
+ //===========================================================================
+ //
+ // D A T A P R O V I D E R
+ //
+ //===========================================================================
+
+ /**
+ * Provides a single DN to search a workflow in a network group.
+ *
+ * Each set of DNs is composed of:
+ * - one baseDN
+ * - one subordinateDN
+ * - a boolean telling whether we expect to find a workflow for the baseDN
+ *
+ * @return set of DNs
+ * @throws Exception when DN.decode fails
+ */
+ @DataProvider(name = "DNSet_1")
+ public Object[][] initDNSet_1()
+ throws Exception
+ {
+ DN dnRootDSE = null;
+ DN dnConfig = null;
+ DN dnMonitor = null;
+ DN dnSchema = null;
+ DN dnTasks = null;
+ DN dnBackups = null;
+ DN dnDummy = null;
+
+ DN dnSubordinateConfig = null;
+ DN dnSubordinateMonitor = null;
+ DN dnSubordinateTasks = null;
+
+ try
+ {
+ dnRootDSE = DN.decode("");
+ dnConfig = DN.decode("cn=config");
+ dnMonitor = DN.decode("cn=monitor");
+ dnSchema = DN.decode("cn=schema");
+ dnTasks = DN.decode("cn=tasks");
+ dnBackups = DN.decode("cn=backups");
+ dnDummy = DN.decode("o=dummy_suffix");
+
+ dnSubordinateConfig = DN.decode("cn=Work Queue,cn=config");
+ dnSubordinateMonitor = DN.decode("cn=schema Backend,cn=monitor");
+ dnSubordinateTasks = DN.decode("cn=Scheduled Tasks,cn=tasks");
+
+ // No DN subordinate for schema because the schema backend is
+ // currently empty.
+ // No DN subordinate for cn=backups because by default there is no
+ // child entry under cn=backups.
+ }
+ catch (DirectoryException de)
+ {
+ throw de;
+ }
+
+ // Sets of DNs
+ Object[][] myData =
+ {
+ { dnRootDSE, null, true },
+ { dnConfig, dnSubordinateConfig, true },
+ { dnMonitor, dnSubordinateMonitor, true },
+ { dnTasks, dnSubordinateTasks, true },
+ { dnSchema, null, true },
+ { dnBackups, null, true },
+ { dnDummy, null, false },
+ };
+
+ return myData;
+ }
+
+ /**
+ * Provides information to create a network group.
+ *
+ * Each set of DNs contains:
+ * - one base DN for the 1st workflow
+ * - one base DN for the 2nd workflow
+ * - one base DN for the 3rd workflow
+ * - one subordinate DN for the 1st workflow
+ * - one subordinate DN for the 2nd workflow
+ * - one subordinate DN for the 3rd workflow
+ * - one unrelated DN which has no hierarchical relationship with
+ * any of the above DNs
+
+ */
+ @DataProvider (name = "DNSet_2")
+ public Object[][] initDNSet_2()
+ throws Exception
+ {
+ // Network group definition
+ DN dn1 = null;
+ DN dn2 = null;
+ DN dn3 = null;
+ DN subordinate1 = null;
+ DN subordinate2 = null;
+ DN subordinate3 = null;
+ DN unrelatedDN = null;
+ try
+ {
+ dn1 = DN.decode("o=test1");
+ dn2 = DN.decode("o=test2");
+ dn3 = DN.decode("o=test3");
+ subordinate1 = DN.decode("ou=subtest1,o=test1");
+ subordinate2 = DN.decode("ou=subtest2,o=test2");
+ subordinate3 = DN.decode("ou=subtest3,o=test3");
+ unrelatedDN = DN.decode("o=dummy");
+ }
+ catch (DirectoryException de)
+ {
+ throw de;
+ }
+
+ // Network group info
+ Object[][] myData =
+ {
+ // Test1: one DN for one workflow
+ {
+ dn1,
+ null,
+ null,
+ subordinate1,
+ null,
+ null,
+ unrelatedDN
+ },
+ // Test2: two DNs for two workflows
+ {
+ dn1,
+ dn2,
+ null,
+ subordinate1,
+ subordinate2,
+ null,
+ unrelatedDN
+ },
+ // Test3: three DNs for three workflows
+ {
+ dn1,
+ dn2,
+ dn3,
+ subordinate1,
+ subordinate2,
+ subordinate3,
+ unrelatedDN
+ }
+ };
+
+ return myData;
+ }
+
+
+ //===========================================================================
+ //
+ // T E S T C A S E S
+ //
+ //===========================================================================
+
+ /**
+ * Gets a workflow candidate in the default network group.
+ *
+ * @param dnToSearch the DN of a workflow in the default network group
+ * @param dnSubordinate a subordinate of dnToSearch
+ * @param exists true if we are supposed to find a workflow for
+ * dnToSearch
+ */
+ @Test (dataProvider = "DNSet_1", groups = "virtual")
+ public void checkDefaultNetworkGroup(
+ DN dnToSearch,
+ DN dnSubordinate,
+ boolean exists
+ )
+ {
+ // let's get the default network group (it should always exist)
+ NetworkGroup defaultNG = NetworkGroup.getDefaultNetworkGroup();
+ assertNotNull(defaultNG);
+
+ // let's check the routing through the network group
+ doCheckNetworkGroup(defaultNG, dnToSearch, dnSubordinate, exists);
+
+ // Dump info
+ StringBuffer sb = defaultNG.toString("defaultNetworkGroup> ");
+ writeln(sb.toString());
+ }
+
+
+ /**
+ * Checks the DN routing through a network group.
+ *
+ * @param networkGroup the network group to use for the check
+ * @param dnToSearch the DN of a workflow in the network group
+ * @param dnSubordinate a subordinate of dnToSearch
+ * @param shouldExist true if we are supposed to find a workflow for
+ * dnToSearch
+ */
+ private void doCheckNetworkGroup(
+ NetworkGroup networkGroup,
+ DN dnToSearch,
+ DN dnSubordinate,
+ boolean shouldExist
+ )
+ {
+ // Let's retrieve the workflow that maps best the dnToSearch
+ Workflow workflow = networkGroup.getWorkflowCandidate(dnToSearch);
+ if (shouldExist)
+ {
+ assertNotNull(workflow);
+ }
+ else
+ {
+ assertNull(workflow);
+ }
+
+ // let's retrieve the workflow that handles the DN subordinate:
+ // it should be the same than the one for dnToSearch
+ if (dnSubordinate != null)
+ {
+ Workflow workflow2 = networkGroup.getWorkflowCandidate(dnSubordinate);
+ assertEquals(workflow2, workflow);
+ }
+ }
+
+
+ /**
+ * Creates a network group with several workflows inside. Routing operation
+ * is done through the default root DSE workflow (which is automatically
+ * created by the network group class).
+ *
+ * @param dn1 the DN for the 1st workflow
+ * @param dn2 the DN for the 2nd workflow
+ * @param dn3 the DN for the 3rd workflow
+ * @param subordinate1 the subordinate DN for the 1st workflow
+ * @param subordinate2 the subordinate DN for the 2nd workflow
+ * @param subordinate3 the subordinate DN for the 3rd workflow
+ * @param unrelatedDN a DN with no hierarchical relationship with
+ * any of the DNs above
+ */
+ @Test (dataProvider = "DNSet_2", groups = "virtual")
+ public void createNetworkGroup2(
+ DN dn1,
+ DN dn2,
+ DN dn3,
+ DN subordinate1,
+ DN subordinate2,
+ DN subordinate3,
+ DN unrelatedDN
+ )
+ {
+ String networkGroupName = "Network Group for test2";
+
+ // Create the network group
+ NetworkGroup ng = new NetworkGroup(networkGroupName);
+ assertNotNull(ng);
+
+ // Register the network group
+ NetworkGroup.registerNetworkGroup(ng);
+
+ // Create and register workflow 1
+ if (dn1 != null)
+ {
+ createAndRegisterWorkflow(ng, dn1, subordinate1, unrelatedDN);
+ }
+
+ // Create and register workflow 2
+ if (dn2 != null)
+ {
+ createAndRegisterWorkflow(ng, dn2, subordinate2, unrelatedDN);
+ }
+
+ // Create and register workflow 3
+ if (dn3 != null)
+ {
+ createAndRegisterWorkflow(ng, dn3, subordinate3, unrelatedDN);
+ }
+
+ // Dump info
+ StringBuffer sb = ng.toString("createNetworkGroup2(" + dn1 + ")> ");
+ writeln(sb.toString());
+
+ // Dump info of defaultNetworkGroup
+ StringBuffer sb2 =
+ NetworkGroup.getDefaultNetworkGroup().toString("defaultNetworkGroup> ");
+ writeln(sb2.toString());
+
+ // Deregister the workflow1...
+ deregisterWorkflow(ng, dn1, subordinate1, unrelatedDN);
+
+ // ... and dump info again
+ sb = ng.toString("DEREGISTER Workflow> ");
+ writeln(sb.toString());
+
+ // dump info of defaultNetworkGroup
+ sb2 = NetworkGroup.getDefaultNetworkGroup().toString(
+ "DEREGISTER defaultNetworkGroup> "
+ );
+ writeln(sb2.toString());
+ }
+
+
+ /**
+ * Creates a workflow and register it with a network group.
+ *
+ * @param networkGroup a network group to register the workflow with
+ * @param workflowBaseDN the base DN of the workflow to register
+ * @param subordinateDN subordinate DN of the workflowBaseDN
+ * @param unrelatedDN a DN with no hierarchical relationship with
+ * any of the base DN above
+ */
+ private void createAndRegisterWorkflow(
+ NetworkGroup networkGroup,
+ DN workflowBaseDN,
+ DN subordinateDN,
+ DN unrelatedDN
+ )
+ {
+ assertNotNull(networkGroup);
+
+ // Create and register a workflow (no task in the workflow)
+ WorkflowElement rootWE = null;
+ WorkflowImpl realWorkflow = new WorkflowImpl(workflowBaseDN, rootWE);
+ assertNotNull(realWorkflow);
+
+ // Register the workflow with the network group.
+ networkGroup.registerWorkflow(realWorkflow);
+
+ // Now check that workflow is accessible through the network group
+ Workflow electedWorkflow;
+ electedWorkflow = networkGroup.getWorkflowCandidate(workflowBaseDN);
+ assertEquals(electedWorkflow.getBaseDN(), workflowBaseDN);
+
+ electedWorkflow = networkGroup.getWorkflowCandidate(subordinateDN);
+ assertEquals(electedWorkflow.getBaseDN(), workflowBaseDN);
+
+ // Check that the unrelatedDN is not handled by the workflow
+ Workflow unrelatedWorkflow =
+ networkGroup.getWorkflowCandidate(unrelatedDN);
+ assertNull(unrelatedWorkflow);
+ }
+
+
+ /**
+ * Deregisters a workflow with a network group. The workflow to
+ * deregister is identified by its baseDN.
+ *
+ * @param networkGroup a network group that contains the workflow
+ * to deregister
+ * @param workflowBaseDN the base DN of the workflow to deregister
+ * @param subordinateDN subordinate DN of the workflowBaseDN
+ * @param unrelatedDN a DN with no hierarchical relationship with
+ * any of the base DN above
+ */
+ private void deregisterWorkflow(
+ NetworkGroup networkGroup,
+ DN workflowBaseDN,
+ DN subordinateDN,
+ DN unrelatedDN
+ )
+ {
+ assertNotNull(networkGroup);
+
+ // get the workflow in the network group
+ Workflow workflow = networkGroup.getWorkflowCandidate(workflowBaseDN);
+ if (workflow == null)
+ {
+ // found no workflow
+ return;
+ }
+
+ // Deregister the workflow with the network group
+ networkGroup.deregisterWorkflow(workflow.getBaseDN());
+
+ // Check that the workflow is no more accessible through the network
+ // group
+ Workflow electedWorkflow;
+ electedWorkflow = networkGroup.getWorkflowCandidate(workflowBaseDN);
+ assertNull(electedWorkflow);
+ electedWorkflow = networkGroup.getWorkflowCandidate(subordinateDN);
+ assertNull(electedWorkflow);
+ }
+
+
+ /**
+ * Prints a text to System.out.
+ */
+ private void write(String msg)
+ {
+ boolean dumpInfo = true;
+
+ if (dumpInfo)
+ {
+ System.out.print(msg);
+ }
+ }
+
+
+ /**
+ * Prints a text to System.out.
+ */
+ private void writeln(String msg)
+ {
+ write(msg + "\n");
+ }
+}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java
index ef8101a..9864e15 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/SearchOperationTestCase.java
@@ -182,7 +182,7 @@
return new Operation[]
{
- new SearchOperation(conn,
+ new SearchOperationBasis(conn,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
new ArrayList<Control>(),
@@ -203,7 +203,7 @@
*
* @param searchOperation The operation to be tested.
*/
- private void examineCompletedOperation(SearchOperation searchOperation)
+ private void examineCompletedOperation(SearchOperationBasis searchOperation)
{
assertTrue(searchOperation.getProcessingStartTime() > 0);
assertTrue(searchOperation.getProcessingStopTime() > 0);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java
new file mode 100644
index 0000000..265fe7c
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/core/WorkflowTopologyTest.java
@@ -0,0 +1,938 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.core;
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import java.util.ArrayList;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.util.UtilTestCase;
+import org.opends.server.workflowelement.WorkflowElement;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+/**
+ * This set of tests checks that workflow topology is properly created.
+ * Topology is based on DN hierarchical relationship. Once the topolofy
+ * is created, we check that the route operation returns the best workflow
+ * candidate for a given request base DN.
+ */
+public class WorkflowTopologyTest extends UtilTestCase
+{
+ //===========================================================================
+ //
+ // B E F O R E C L A S S
+ //
+ //===========================================================================
+
+ /**
+ * Set up the environment for performing the tests in this suite.
+ *
+ * @throws Exception if the environment could not be set up.
+ */
+ @BeforeClass
+ public void setUp()
+ throws Exception
+ {
+ // This test suite depends on having the schema available,
+ // so we'll start the server.
+ TestCaseUtils.startServer();
+ }
+
+
+ //===========================================================================
+ //
+ // D A T A P R O V I D E R
+ //
+ //===========================================================================
+
+ /**
+ * Provide a set of DNs to create a single workflow. Each set of DNs contains
+ * one baseDN for the new workflow to be created, one subordinateDN and one
+ * unrelatedDN which has no hierarchical relationship with the baseDN.
+ *
+ * baseDN + subordinateDN + unrelatedDN
+ *
+ * Sample scenario for a test using this set of DNs:
+ * 1) creating a workflow with the baseDN
+ * 2) trying to fetch the workflow using the subordinateDN
+ * 3) checking that the workflow cannot be candidate to route a request
+ * with the unrelatedDN
+ *
+ * @return set of DNs
+ * @throws Exception when DN.decode fails
+ */
+ @DataProvider(name = "DNSet_1")
+ public Object[][] initDNSet_1()
+ throws Exception
+ {
+ DN dnNull = null;
+ DN baseDN1 = null;
+ DN subordinateDN1 = null;
+ DN unrelatedDN = null;
+
+ try
+ {
+ dnNull = DN.decode ("");
+ baseDN1 = DN.decode ("o=test");
+ subordinateDN1 = DN.decode ("ou=subtest,o=test");
+ unrelatedDN = DN.decode ("o=dummy");
+ }
+ catch (DirectoryException de)
+ {
+ throw de;
+ }
+
+ // Sets of DNs
+ Object[][] myData =
+ {
+ // SET 1
+ // baseDN is null suffix. There is no unrelatedDN because any DN
+ // is descendant of the null suffix.
+ {
+ dnNull,
+ subordinateDN1,
+ null
+ },
+
+ // SET 2
+ // One baseDN, one subordinateDN and one unrelatedDN
+ {
+ baseDN1,
+ subordinateDN1,
+ unrelatedDN
+ },
+ };
+
+ return myData;
+ }
+
+
+ /**
+ * Provide a set of DNs to create a topology of 3 workflows, and the 3
+ * workflows are in the same hierarchy of DNs: baseDN1 is the superior
+ * of baseDN2 which is the superior of baseDN3:
+ *
+ * baseDN1 + subordinateDN1
+ * |
+ * baseDN2 + subordinateDN2 + unrelatedDN
+ * |
+ * baseDN3 + subordinateDN3
+ *
+ * Each baseDN has a subordinateDN: the workflow with the baseDN should be
+ * the candidate for a request when request base DN is the subordinateDN.
+ *
+ * There is an unrelatedDN which has no hierarchical relationship with any
+ * of the baseDNs. The unrelatedDN is used to check that none of the
+ * workflow can be candidate for the route when a request is using the
+ * unrelatedDN.
+ *
+ * @return set of DNs
+ * @throws Exception when DN.decode fails
+ */
+ @DataProvider(name = "DNSet_2")
+ public Object[][] initDNSet_2()
+ throws Exception
+ {
+ DN unrelatedDN = null;
+ int nbElem = 3;
+ DN[] baseDNs = new DN[nbElem];
+ DN[] subordinateDNs = new DN[nbElem];
+ DN rootDSE = null;
+
+ // Create the topology of DNs:
+ //
+ // o=dummy ou=test1 (==> W1)
+ // |
+ // |
+ // +--------------+
+ // | |
+ // | |
+ // ou=subordinate1 ou=test2 (==> W2)
+ // |
+ // |
+ // +--------------------+
+ // | |
+ // | |
+ // ou=test3 (==> W3) ou=subordinate2
+ // |
+ // |
+ // +--------------+
+ // | |
+ // | |
+ // ou=subordinate3
+ try
+ {
+ String suffix = "ou=test1";
+ String baseDN1 = suffix;
+ String baseDN2 = "ou=test2," + baseDN1;
+ String baseDN3 = "ou=test3," + baseDN2;
+ String subordinateDN1 = "ou=subordinate1," + baseDN1;
+ String subordinateDN2 = "ou=subordinate2," + baseDN2;
+ String subordinateDN3 = "ou=subordinate3," + baseDN3;
+
+ int i = 0;
+ baseDNs[i] = DN.decode (baseDN1);
+ subordinateDNs[i] = DN.decode (subordinateDN1);
+ i++;
+ baseDNs[i] = DN.decode (baseDN2);
+ subordinateDNs[i] = DN.decode (subordinateDN2);
+ i++;
+ baseDNs[i] = DN.decode (baseDN3);
+ subordinateDNs[i] = DN.decode (subordinateDN3);
+
+ unrelatedDN = DN.decode ("o=dummy");
+ rootDSE = DN.decode ("");
+ }
+ catch (DirectoryException de)
+ {
+ throw de;
+ }
+
+ // Sets of DNs
+ Object[][] myData =
+ {
+ // SET 1
+ {
+ baseDNs[0], baseDNs[1], baseDNs[2],
+ subordinateDNs[0], subordinateDNs[1], subordinateDNs[2],
+ unrelatedDN
+ },
+
+ // SET 2
+ // Same than SET 1, but the first baseDN is the null suffix DN.
+ // Hence there is no unrelatedDN as any DN is a subordinate of
+ // the null suffix.
+ {
+ rootDSE, baseDNs[1], baseDNs[2],
+ subordinateDNs[0], subordinateDNs[1], subordinateDNs[2],
+ null
+ }
+ };
+
+ return myData;
+ }
+
+
+ /**
+ * Provide a set of DNs to create the following topology:
+ *
+ * [W1]
+ * baseDN1
+ * |
+ * +---------+--------+
+ * | |
+ * | |
+ * subordinateDN1 +------+------+
+ * | |
+ * [W2] [W3]
+ * baseDN2 baseDN3
+ * | |
+ * | |
+ * subordinateDN2 subordinateDN3
+ *
+ *
+ * @return set of DNs
+ * @throws Exception when DN.decode fails
+ */
+ @DataProvider(name = "DNSet_3")
+ public Object[][] initDNSet_3()
+ throws Exception
+ {
+ DN unrelatedDN = null;
+ int nbElem = 3;
+ DN[] baseDNs = new DN[nbElem];
+ DN[] subordinateDNs = new DN[nbElem];
+ DN rootDSE = null;
+
+ // Create the topology of DNs:
+ //
+ // o=dummy dc=example,dc=com
+ // |
+ // |
+ // +--------------+-----------------+
+ // | | |
+ // ou=subordinate1 ou=group ou=people
+ // | |
+ // | |
+ // ou=subordinate2 ou=subordinate3
+ try
+ {
+ String suffix = "dc=example,dc=com";
+ String baseDN1 = suffix;
+ String baseDN2 = "ou=group," + baseDN1;
+ String baseDN3 = "ou=people," + baseDN1;
+ String subordinateDN1 = "ou=subordinate1," + baseDN1;
+ String subordinateDN2 = "ou=subordinate2," + baseDN2;
+ String subordinateDN3 = "ou=subordinate3," + baseDN3;
+
+ int i = 0;
+ baseDNs[i] = DN.decode (baseDN1);
+ subordinateDNs[i] = DN.decode (subordinateDN1);
+ i++;
+ baseDNs[i] = DN.decode (baseDN2);
+ subordinateDNs[i] = DN.decode (subordinateDN2);
+ i++;
+ baseDNs[i] = DN.decode (baseDN3);
+ subordinateDNs[i] = DN.decode (subordinateDN3);
+
+ unrelatedDN = DN.decode ("o=dummy");
+ rootDSE = DN.decode ("");
+ }
+ catch (DirectoryException de)
+ {
+ throw de;
+ }
+
+ // Sets of DNs
+ Object[][] myData =
+ {
+ // SET 1
+ //
+ // o=dummy dc=example,dc=com
+ // |
+ // |
+ // +--------------+-----------------+
+ // | | |
+ // ou=subordinate1 ou=group ou=people
+ // | |
+ // | |
+ // ou=subordinate2 ou=subordinate3
+ {
+ baseDNs[0],
+ baseDNs[1],
+ baseDNs[2],
+ subordinateDNs[0],
+ subordinateDNs[1],
+ subordinateDNs[2],
+ unrelatedDN
+ },
+
+ // SET 2
+ //
+ // The top baseDN is the null suffix. Hence there is no unrelatedDN
+ // as any DN is a subordinate of the null suffix.
+ //
+ // "" (rootDSE)
+ // |
+ // |
+ // +--------------+-----------------+
+ // | | |
+ // ou=subordinate1 ou=group ou=people
+ // | |
+ // | |
+ // ou=subordinate2 ou=subordinate3
+ {
+ rootDSE,
+ baseDNs[1],
+ baseDNs[2],
+ subordinateDNs[0],
+ subordinateDNs[1],
+ subordinateDNs[2],
+ null
+ }
+ };
+
+ return myData;
+ }
+
+
+ /**
+ * Provide a set of result codes to test the elaboration of the global
+ * result code.
+ *
+ * @return set of result codes to test
+ * @throws Exception
+ */
+ @DataProvider(name = "ResultCodes_1")
+ public Object[][] initResultCodes_1()
+ {
+ // Short names...
+ ResultCode rcSuccess = ResultCode.SUCCESS;
+ ResultCode rcNoSuchObject = ResultCode.NO_SUCH_OBJECT;
+ ResultCode rcReferral = ResultCode.REFERRAL;
+ ResultCode rcOther = ResultCode.ALIAS_PROBLEM;
+ ResultCode rcOther2 = ResultCode.AUTHORIZATION_DENIED;
+
+ // Sets of DNs
+ Object[][] myData =
+ {
+ // received current expected
+ // result code result code result code
+ { rcSuccess, rcNoSuchObject, rcSuccess },
+ { rcReferral, rcSuccess, rcSuccess },
+ { rcSuccess, rcOther, rcOther },
+ { rcNoSuchObject, rcSuccess, rcSuccess },
+ { rcNoSuchObject, rcReferral, rcReferral },
+ { rcNoSuchObject, rcOther, rcOther },
+ { rcReferral, rcSuccess, rcSuccess },
+ { rcReferral, rcReferral, rcSuccess },
+ { rcReferral, rcNoSuchObject, rcReferral },
+ { rcReferral, rcOther, rcOther },
+ { rcOther, rcSuccess, rcOther },
+ { rcOther, rcReferral, rcOther },
+ { rcOther, rcNoSuchObject, rcOther },
+ { rcOther, rcOther2, rcOther2 }
+ };
+
+ return myData;
+ }
+
+
+ //===========================================================================
+ //
+ // T E S T C A S E S
+ //
+ //===========================================================================
+
+ /**
+ * Create a single workflow using a baseDN. There is no workflow element
+ * in the workflow nor in the DIT attached to the workflow. Once the
+ * workflow has been created, we are trying to fetch it using the baseDN
+ * and/or the subordinateDN and/or the unrelatedDN.
+ *
+ * @param baseDN baseDN of the workflow to create
+ * @param subordinateDN a subordinate DN of baseDN
+ * @param dummyDN a DN not registered in any workflow
+ */
+ @Test (dataProvider = "DNSet_1", groups = "virtual")
+ public void createWorkflow_basic (
+ DN baseDN,
+ DN subordinateDN,
+ DN dummyDN
+ )
+ {
+ // create a DIT set with the baseDN (no workflow element in the DIT).
+ WorkflowElement nullWE = null;
+ WorkflowImpl realWorkflow = new WorkflowImpl (baseDN, nullWE);
+
+ // Create a worflow with the dit, no pre/post-workflow element.
+ WorkflowTopologyNode workflow = new WorkflowTopologyNode (realWorkflow, null, null);
+
+ // The base DN in the workflow should match baseDN parameter
+ DN workflowBaseDN = workflow.getBaseDN();
+ assertEquals (workflowBaseDN, baseDN);
+
+ // There should be no parent workflow.
+ WorkflowTopologyNode parent = workflow.getParent();
+ assertEquals (parent, null);
+
+ // The workflow should handle the baseDN and subordinateDN.
+ DN readBaseDN = null;
+ readBaseDN = workflow.getParentBaseDN (baseDN);
+ assertEquals (readBaseDN, baseDN);
+ readBaseDN = workflow.getParentBaseDN (subordinateDN);
+ assertEquals (readBaseDN, baseDN);
+
+ // The workflow should not handle the dummyDN.
+ if (dummyDN != null)
+ {
+ readBaseDN = workflow.getParentBaseDN (dummyDN);
+ assertNull (readBaseDN);
+ }
+
+ } // createWorkflow_basic
+
+
+ /**
+ * Create a topology with 2 workflows. The test case contains creation
+ * of clean topologies as well as bad topologies (same baseDN for the parent
+ * and subordinate, subordinate above parent...).
+ *
+ * W1 (baseDN)
+ * |
+ * |
+ * W2 (subordinateDN)
+ *
+ * There is no worklfow element attached to the DITs.
+ *
+ * @param baseDn base DN for the parent workflow (W1)
+ * @param subordinateDN base DN for the subordinate workflow (W2)
+ * @param unrelatedDN base DN with no hierarchical relationship with any
+ * of the two baseDNs; parameter may be null
+ */
+ @Test (dataProvider = "DNSet_1", groups = "virtual")
+ public void createWorkflow_simpleTopology1(
+ DN baseDN,
+ DN subordinateDN,
+ DN unrelatedDN
+ )
+ {
+ // Create one DIT set for baseDN and one DIT set for subordinateDN
+ // (no workflow element in any DIT). Create a dummy DIT as well using
+ // the unrelatedDN.
+ WorkflowImpl workflow = null;
+ WorkflowImpl subWorkflow = null;
+ WorkflowImpl unrelatedWorkflow = null;
+ {
+ WorkflowElement nullWE = null;
+ workflow = new WorkflowImpl (baseDN, nullWE);
+ subWorkflow = new WorkflowImpl (subordinateDN, nullWE);
+ if (unrelatedDN != null)
+ {
+ unrelatedWorkflow = new WorkflowImpl (unrelatedDN, nullWE);
+ }
+ }
+
+ // Create a worflow for each dit, no pre/post-workflow element
+ WorkflowTopologyNode w1 = new WorkflowTopologyNode (workflow, null, null);
+ WorkflowTopologyNode w1bis = new WorkflowTopologyNode (workflow, null, null);
+ WorkflowTopologyNode w2 = new WorkflowTopologyNode (subWorkflow, null, null);
+
+ WorkflowTopologyNode w3 = null;
+ if (unrelatedWorkflow != null)
+ {
+ w3 = new WorkflowTopologyNode (unrelatedWorkflow, null, null);
+ }
+
+ // insert status
+ boolean insert;
+
+ // Try to create a topology with unrelated workflows:
+ //
+ // w1 (baseDN)
+ // |
+ // w3 (dnDummy)
+ //
+ // Insert should be rejected
+ if (w3 != null)
+ {
+ insert = w1.insertSubordinate (w3);
+ assertEquals (insert, false);
+ }
+
+ // Try to create a topology with the very same workflow:
+ //
+ // w1 (baseDN)
+ // |
+ // w1 (baseDN)
+ //
+ // Insert should be rejected
+ insert = w1.insertSubordinate (w1);
+ assertEquals (insert, false);
+
+ // Try to create a topology with a workflow whose baseDN is the same than
+ // parent baseDN:
+ //
+ // w1 (baseDN)
+ // |
+ // w1bis (baseDN)
+ //
+ // Insert should be rejected
+ insert = w1.insertSubordinate (w1bis);
+ assertEquals (insert, false);
+
+ // Try to create a topology where subordinate is above the parent:
+ //
+ // w2 (subordinateDN)
+ // |
+ // w1 (baseDN)
+ //
+ // Insert should be rejected
+ insert = w2.insertSubordinate (w1);
+ assertEquals (insert, false);
+
+ // Try to create a clean topology:
+ //
+ // w1 (baseDN)
+ // |
+ // w2 (subordinateDN)
+ //
+ // Expected results:
+ //
+ // - insert should be working
+ insert = w1.insertSubordinate (w2);
+ assertEquals (insert, true);
+
+ // - w1 should be the parent of w2
+ WorkflowTopologyNode parent1 = w2.getParent();
+ assertEquals (parent1, w1);
+
+ // - w2 should be in the w1 subordinate list
+ ArrayList<WorkflowTopologyNode> subordinates1 = w1.getSubordinates();
+ assertEquals (subordinates1.size(), 1);
+ assertEquals (subordinates1.get(0), w2);
+
+ // - w2 should have no subordinate
+ ArrayList<WorkflowTopologyNode> subordinates2 = w2.getSubordinates();
+ assertEquals (subordinates2.size(), 0);
+
+ } // createWorkflow_simpleTopology1
+
+
+ /**
+ * Create a topology with 3 workflows and check that we are getting the
+ * right workflow for a given DN. Then remove a workflow in the chain and
+ * check that topology is properly updated in term of parent/subordinate
+ * links.
+ *
+ * W1 (baseDN1)
+ * |
+ * +----> subordinateDN1
+ * |
+ * W2 (baseDN2)
+ * |
+ * +----> subordinateDN2
+ * |
+ * W3 (baseDN3)
+ * |
+ * +----> subordinateDN3
+ * |
+ *
+ * There is no worklfow element attached to the DITs.
+ *
+ * @param baseDn1 base DN for the top workflow (W1)
+ * @param baseDN2 base DN for the first subordinate workflow (W2)
+ * @param baseDN3 base DN for the second subordinate workflow (W3)
+ * @param subordinateDN1 subordinate DN of baseDN1
+ * @param subordinateDN2 subordinate DN of baseDN2
+ * @param subordinateDN3 subordinate DN of baseDN3
+ * @param unrelatedDN a DN not registered in any workflow
+ */
+ @Test (dataProvider = "DNSet_2", groups = "virtual")
+ public void createWorkflow_simpleTopology2(
+ DN baseDN1,
+ DN baseDN2,
+ DN baseDN3,
+ DN subordinateDN1,
+ DN subordinateDN2,
+ DN subordinateDN3,
+ DN unrelatedDN
+ )
+ {
+ // Create a worflow for each baseDN, no pre/post-workflow element
+ WorkflowTopologyNode w1;
+ WorkflowTopologyNode w2;
+ WorkflowTopologyNode w3;
+ {
+ // create DITs with the given baseDNs with no workflow element.
+ WorkflowImpl workflow1;
+ WorkflowImpl workflow2;
+ WorkflowImpl workflow3;
+ {
+ WorkflowElement nullWE = null;
+ workflow1 = new WorkflowImpl (baseDN1, nullWE);
+ workflow2 = new WorkflowImpl (baseDN2, nullWE);
+ workflow3 = new WorkflowImpl(baseDN3, nullWE);
+ }
+
+ w1 = new WorkflowTopologyNode (workflow1, null, null);
+ w2 = new WorkflowTopologyNode (workflow2, null, null);
+ w3 = new WorkflowTopologyNode (workflow3, null, null);
+ }
+
+ // insert status
+ boolean insert;
+
+ // Create a first topology with:
+ //
+ // w1 (baseDN1)
+ // |
+ // w3 (baseDN3)
+ //
+ insert = w1.insertSubordinate (w3);
+ assertEquals (insert, true);
+
+ // Now insert w2 between w1 and w3
+ //
+ // w1 (baseDN1)
+ // |
+ // w2 (baseDN2)
+ // |
+ // w3 (baseDN3)
+ //
+ insert = w1.insertSubordinate (w2);
+ assertEquals (insert, true);
+
+ // Check the topology:
+ // - w1 has no parent and has only w2 as subordinate
+ WorkflowTopologyNode parent = w1.getParent();
+ assertNull (parent);
+ ArrayList<WorkflowTopologyNode> subordinates = w1.getSubordinates();
+ assertEquals (subordinates.size(), 1);
+ assertEquals (subordinates.get(0), w2);
+
+ // - w2 has w1 as parent and w3 as subordinate
+ parent = w2.getParent();
+ assertEquals (parent, w1);
+ subordinates = w2.getSubordinates();
+ assertEquals (subordinates.size(), 1);
+ assertEquals (subordinates.get(0), w3);
+
+ // -w3 has w2 as parent and no subordinate
+ parent = w3.getParent();
+ assertEquals (parent, w2);
+ subordinates = w3.getSubordinates();
+ assertEquals (subordinates.size(), 0);
+
+ // ======================================================
+ // Topology is clean, now let's check the route algorithm.
+ // ======================================================
+
+ DN readDN1 = null;
+ DN readDN2 = null;
+ DN readDN3 = null;
+
+ // subordinate1 should be handled by w1 only
+ readDN1 = w1.getParentBaseDN (subordinateDN1);
+ readDN2 = w1.getParentBaseDN (subordinateDN2);
+ readDN3 = w1.getParentBaseDN (subordinateDN3);
+ assertEquals (readDN1, baseDN1);
+ assertEquals (readDN2, baseDN2);
+ assertEquals (readDN3, baseDN3);
+
+ // subordinate2 should be handled by w2 only
+ readDN1 = w2.getParentBaseDN (subordinateDN1);
+ readDN2 = w2.getParentBaseDN (subordinateDN2);
+ readDN3 = w2.getParentBaseDN (subordinateDN3);
+ assertEquals (readDN1, null);
+ assertEquals (readDN2, baseDN2);
+ assertEquals (readDN3, baseDN3);
+
+ // subordinate3 should be handled by w3 only
+ readDN1 = w3.getParentBaseDN (subordinateDN1);
+ readDN2 = w3.getParentBaseDN (subordinateDN2);
+ readDN3 = w3.getParentBaseDN (subordinateDN3);
+ assertEquals (readDN1, null);
+ assertEquals (readDN2, null);
+ assertEquals (readDN3, baseDN3);
+
+ // unrelatedDN should be handled by none of the workflows
+ readDN1 = w1.getParentBaseDN (unrelatedDN);
+ readDN2 = w2.getParentBaseDN (unrelatedDN);
+ readDN3 = w3.getParentBaseDN (unrelatedDN);
+ assertEquals (readDN1, null);
+ assertEquals (readDN2, null);
+ assertEquals (readDN3, null);
+
+ // ======================================================
+ // Remove a workflow in the chain and check that
+ // the route algorithm is still working
+ // ======================================================
+
+ // Remove w2...
+ //
+ // w1 (baseDN1) w1
+ // | |
+ // w2 (baseDN2) ==> |
+ // | |
+ // w3 (baseDN3) w3
+ //
+ w2.remove();
+
+ // subordinate1 and subordinate2 should now be handled by w1 only
+ readDN1 = w1.getParentBaseDN (subordinateDN1);
+ readDN2 = w1.getParentBaseDN (subordinateDN2);
+ readDN3 = w1.getParentBaseDN (subordinateDN3);
+ assertEquals (readDN1, baseDN1);
+ assertEquals (readDN2, baseDN1); // was baseDN2 before the removal...
+ assertEquals (readDN3, baseDN3);
+
+ // sanity check1
+ // subordinate3 should be handled by w3 only
+ readDN1 = w3.getParentBaseDN (subordinateDN1);
+ readDN2 = w3.getParentBaseDN (subordinateDN2);
+ readDN3 = w3.getParentBaseDN (subordinateDN3);
+ assertEquals (readDN1, null);
+ assertEquals (readDN2, null);
+ assertEquals (readDN3, baseDN3);
+
+ // sanity check2
+ // unrelatedDN should be handled by none of the workflows
+ readDN1 = w1.getParentBaseDN (unrelatedDN);
+ readDN2 = w2.getParentBaseDN (unrelatedDN);
+ readDN3 = w3.getParentBaseDN (unrelatedDN);
+ assertEquals (readDN1, null);
+ assertEquals (readDN2, null);
+ assertEquals (readDN3, null);
+
+ } // createWorkflow_simpleTopology2
+
+
+ /**
+ * Create a topology of workflows.
+ *
+ * W1
+ * baseDN1
+ * /\
+ * / \
+ * / \
+ * W2 W3
+ * baseDN2 baseDN3
+ *
+ * There is no worklfow element attached to the DITs.
+ *
+ * @param baseDn1 base DN for the top workflow (W1)
+ * @param baseDN2 base DN for the first subordinate workflow (W2)
+ * @param baseDN3 base DN for the second subordinate workflow (W3)
+ * @param subordinateDN1 subordinate DN of baseDN1
+ * @param subordinateDN2 subordinate DN of baseDN2
+ * @param subordinateDN3 subordinate DN of baseDN3
+ * @param unrelatedDN a DN not registered in any workflow
+ */
+ @Test (dataProvider = "DNSet_3", groups = "virtual")
+ public void createWorkflow_complexTopology1 (
+ DN baseDN1,
+ DN baseDN2,
+ DN baseDN3,
+ DN subordinateDN1,
+ DN subordinateDN2,
+ DN subordinateDN3,
+ DN unrelatedDN
+ )
+ {
+ // Create a worflow for each baseDN, no pre/post-workflow element
+ WorkflowTopologyNode w1;
+ WorkflowTopologyNode w2;
+ WorkflowTopologyNode w3;
+ {
+ // create DITs with the given baseDNs with no workflow element.
+ WorkflowImpl workflow1;
+ WorkflowImpl workflow2;
+ WorkflowImpl workflow3;
+ {
+ WorkflowElement nullWE = null;
+
+ workflow1 = new WorkflowImpl (baseDN1, nullWE);
+ workflow2 = new WorkflowImpl (baseDN2, nullWE);
+ workflow3 = new WorkflowImpl (baseDN3, nullWE);
+ }
+
+ w1 = new WorkflowTopologyNode (workflow1, null, null);
+ w2 = new WorkflowTopologyNode (workflow2, null, null);
+ w3 = new WorkflowTopologyNode (workflow3, null, null);
+ }
+
+ // Put all the workflows in a pool
+ WorkflowTopologyNode[] workflowPool = {w1, w2, w3};
+
+ // Create the workflow topology: to do so, try to insert each workflow
+ // in the other workflows. This is basically how workflow topology is
+ // built by the network group.
+ for (WorkflowTopologyNode parent: workflowPool)
+ {
+ for (WorkflowTopologyNode subordinate: workflowPool)
+ {
+ if (parent == subordinate)
+ {
+ // makes no sense to try to insert a workflow in itself!
+ // let's do it anyway... but it should fail ;-)
+ boolean insertDone = parent.insertSubordinate (parent);
+ assertEquals (insertDone, false);
+ }
+ else
+ {
+ if (parent.insertSubordinate (subordinate))
+ {
+ // insert done
+ }
+ }
+ }
+ }
+
+ // Check the topology
+ // ------------------
+
+ // W1 should have 2 subordinates: W2 and W3
+ ArrayList<WorkflowTopologyNode> subordinates1 = w1.getSubordinates();
+ assertEquals (subordinates1.size(), 2);
+
+ // W2 and W3 should have no subordinate
+ ArrayList<WorkflowTopologyNode> subordinates2 = w2.getSubordinates();
+ assertEquals (subordinates2.size(), 0);
+ ArrayList<WorkflowTopologyNode> subordinates3 = w3.getSubordinates();
+ assertEquals (subordinates3.size(), 0);
+
+ // W1 should be the parent of W2 and W3
+ WorkflowTopologyNode parent2 = w2.getParent();
+ assertEquals (parent2, w1);
+ WorkflowTopologyNode parent3 = w3.getParent();
+ assertEquals (parent3, w1);
+
+ // Check the route algorithm
+ // -------------------------
+
+ // candidate for baseDN1 and subordinateBaseDN1 should be W1
+ WorkflowTopologyNode candidate1 = w1.getWorkflowCandidate (baseDN1);
+ assertEquals (candidate1, w1);
+ candidate1 = w1.getWorkflowCandidate (subordinateDN1);
+ assertEquals (candidate1, w1);
+
+ // candidate for baseDN2/3 and subordinateBaseDN2/3 should be W2/3
+ WorkflowTopologyNode candidate2 = w1.getWorkflowCandidate (baseDN2);
+ assertEquals (candidate2, w2);
+ candidate2 = w1.getWorkflowCandidate (subordinateDN2);
+ assertEquals (candidate2, w2);
+
+ WorkflowTopologyNode candidate3 = w1.getWorkflowCandidate (baseDN3);
+ assertEquals (candidate3, w3);
+ candidate3 = w1.getWorkflowCandidate (subordinateDN3);
+ assertEquals (candidate3, w3);
+
+ // there should be no candidate for dummyDN
+ if (unrelatedDN != null)
+ {
+ WorkflowTopologyNode candidateDummy = w1.getWorkflowCandidate (unrelatedDN);
+ assertEquals (candidateDummy, null);
+ }
+
+ // dump the topology
+ StringBuffer sb = w1.toString ("");
+ System.out.println (sb);
+
+ } // createWorkflow_complexTopology1
+
+
+ /**
+ * Test the elaboration of the global result code by the workflow.
+ */
+ @Test (dataProvider = "ResultCodes_1", groups = "virtual")
+ public void testGlobalResultCode(
+ ResultCode receivedResultCode,
+ ResultCode initialResultCode,
+ ResultCode expectedGlobalResultCode
+ )
+ throws Exception
+ {
+ // Check the function that elaborates the global result code
+ WorkflowResultCode globalResultCode = new WorkflowResultCode (
+ initialResultCode, new StringBuilder("")
+ );
+ globalResultCode.elaborateGlobalResultCode (
+ receivedResultCode, new StringBuilder("")
+ );
+ assertEquals (globalResultCode.resultCode(), expectedGlobalResultCode);
+ }
+}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AnonymousSASLMechanismHandlerTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AnonymousSASLMechanismHandlerTestCase.java
index 683a7a8..5ee6d9a 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AnonymousSASLMechanismHandlerTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AnonymousSASLMechanismHandlerTestCase.java
@@ -34,7 +34,7 @@
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
-import org.opends.server.core.BindOperation;
+import org.opends.server.core.BindOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.tools.LDAPSearch;
@@ -137,8 +137,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- BindOperation bindOperation =
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(), "3", DN.nullDN(),
SASL_MECHANISM_ANONYMOUS, null);
handler.processSASLBind(bindOperation);
@@ -164,8 +164,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- BindOperation bindOperation =
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(), "3", DN.nullDN(),
SASL_MECHANISM_ANONYMOUS, new ASN1OctetString());
handler.processSASLBind(bindOperation);
@@ -190,8 +190,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- BindOperation bindOperation =
- new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ BindOperationBasis bindOperation =
+ new BindOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(), "3", DN.nullDN(),
SASL_MECHANISM_ANONYMOUS,
new ASN1OctetString("Internal Trace String"));
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AttributeValuePasswordValidatorTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AttributeValuePasswordValidatorTestCase.java
index 7edd89a..1503e26 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AttributeValuePasswordValidatorTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/AttributeValuePasswordValidatorTestCase.java
@@ -40,22 +40,18 @@
import org.opends.server.admin.std.meta.AttributeValuePasswordValidatorCfgDefn;
import org.opends.server.admin.std.server.AttributeValuePasswordValidatorCfg;
import org.opends.server.admin.server.AdminTestCaseUtils;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Attribute;
import org.opends.server.types.ByteString;
-import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.Control;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
-import org.opends.server.types.ResultCode;
import static org.testng.Assert.*;
@@ -418,8 +414,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CharacterSetPasswordValidatorTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CharacterSetPasswordValidatorTestCase.java
index db2989d..38ce1a3 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CharacterSetPasswordValidatorTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/CharacterSetPasswordValidatorTestCase.java
@@ -28,7 +28,6 @@
-import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -41,22 +40,18 @@
import org.opends.server.admin.std.meta.CharacterSetPasswordValidatorCfgDefn;
import org.opends.server.admin.std.server.CharacterSetPasswordValidatorCfg;
import org.opends.server.admin.server.AdminTestCaseUtils;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Attribute;
import org.opends.server.types.ByteString;
-import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.Control;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
-import org.opends.server.types.ResultCode;
import static org.testng.Assert.*;
@@ -535,8 +530,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DictionaryPasswordValidatorTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DictionaryPasswordValidatorTestCase.java
index ed7754b..cf50914 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DictionaryPasswordValidatorTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DictionaryPasswordValidatorTestCase.java
@@ -28,9 +28,6 @@
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -43,22 +40,18 @@
import org.opends.server.admin.std.meta.DictionaryPasswordValidatorCfgDefn;
import org.opends.server.admin.std.server.DictionaryPasswordValidatorCfg;
import org.opends.server.admin.server.AdminTestCaseUtils;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Attribute;
import org.opends.server.types.ByteString;
-import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.Control;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
-import org.opends.server.types.ResultCode;
import static org.testng.Assert.*;
@@ -502,8 +495,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProviderTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProviderTestCase.java
index dd6ff2f..0dcfe9b 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProviderTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/EntryDNVirtualAttributeProviderTestCase.java
@@ -55,6 +55,7 @@
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchScope;
import org.opends.server.types.VirtualAttributeRule;
+import org.opends.server.workflowelement.localbackend.LocalBackendSearchOperation;
import static org.testng.Assert.*;
@@ -1101,7 +1102,10 @@
SearchScope.WHOLE_SUBTREE,
DereferencePolicy.NEVER_DEREF_ALIASES, 0,
0, false, filter, null, null);
- provider.processSearch(rule, searchOperation);
+ LocalBackendSearchOperation localSearch =
+ new LocalBackendSearchOperation(searchOperation);
+
+ provider.processSearch(rule, localSearch);
if (shouldMatch)
{
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java
index 5487dbb..e1ae3a8 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java
@@ -57,6 +57,7 @@
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchScope;
import org.opends.server.types.VirtualAttributeRule;
+import org.opends.server.workflowelement.localbackend.LocalBackendSearchOperation;
import static org.testng.Assert.*;
@@ -1113,7 +1114,7 @@
DereferencePolicy.NEVER_DEREF_ALIASES, 0,
0, false, filter, null, null);
- assertEquals(provider.isSearchable(rule, searchOperation), isSearchable);
+ assertEquals(provider.isSearchable(rule, new LocalBackendSearchOperation(searchOperation)), isSearchable);
}
@@ -1237,7 +1238,7 @@
SearchScope.WHOLE_SUBTREE,
DereferencePolicy.NEVER_DEREF_ALIASES, 0,
0, false, filter, null, null);
- provider.processSearch(rule, searchOperation);
+ provider.processSearch(rule, new LocalBackendSearchOperation(searchOperation));
boolean matchFound = false;
for (Entry e : searchOperation.getSearchEntries())
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LengthBasedPasswordValidatorTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LengthBasedPasswordValidatorTestCase.java
index 8c7d071..7e16c57 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LengthBasedPasswordValidatorTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/LengthBasedPasswordValidatorTestCase.java
@@ -45,7 +45,7 @@
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Attribute;
@@ -374,8 +374,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation op =
- new ModifyOperation(conn, conn.nextOperationID(),
+ ModifyOperationBasis op =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), new ArrayList<Control>(),
DN.decode("cn=uid=test.user,o=test"), mods);
@@ -447,8 +447,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation op =
- new ModifyOperation(conn, conn.nextOperationID(),
+ ModifyOperationBasis op =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), new ArrayList<Control>(),
DN.decode("cn=uid=test.user,o=test"), mods);
@@ -522,8 +522,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation op =
- new ModifyOperation(conn, conn.nextOperationID(),
+ ModifyOperationBasis op =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), new ArrayList<Control>(),
DN.decode("cn=uid=test.user,o=test"), mods);
@@ -597,8 +597,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation op =
- new ModifyOperation(conn, conn.nextOperationID(),
+ ModifyOperationBasis op =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), new ArrayList<Control>(),
DN.decode("cn=uid=test.user,o=test"), mods);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RepeatedCharactersPasswordValidatorTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RepeatedCharactersPasswordValidatorTestCase.java
index c0672b7..df4b95d 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RepeatedCharactersPasswordValidatorTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/RepeatedCharactersPasswordValidatorTestCase.java
@@ -42,10 +42,8 @@
import org.opends.server.admin.std.server.
RepeatedCharactersPasswordValidatorCfg;
import org.opends.server.admin.server.AdminTestCaseUtils;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Attribute;
@@ -316,8 +314,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -384,8 +383,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -451,8 +451,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -519,8 +520,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -585,8 +587,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -652,8 +655,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SimilarityBasedPasswordValidatorTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SimilarityBasedPasswordValidatorTestCase.java
index e82d47e..35f5c45 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SimilarityBasedPasswordValidatorTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SimilarityBasedPasswordValidatorTestCase.java
@@ -36,7 +36,7 @@
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Attribute;
@@ -291,8 +291,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation op =
- new ModifyOperation(conn, conn.nextOperationID(),
+ ModifyOperationBasis op =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), new ArrayList<Control>(),
DN.decode("cn=uid=test.user,o=test"), mods);
@@ -367,8 +367,8 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation op =
- new ModifyOperation(conn, conn.nextOperationID(),
+ ModifyOperationBasis op =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
conn.nextMessageID(), new ArrayList<Control>(),
DN.decode("cn=uid=test.user,o=test"), mods);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UniqueCharactersPasswordValidatorTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UniqueCharactersPasswordValidatorTestCase.java
index d5e4fe0..7339811 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UniqueCharactersPasswordValidatorTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UniqueCharactersPasswordValidatorTestCase.java
@@ -42,10 +42,8 @@
import org.opends.server.admin.std.server.
UniqueCharactersPasswordValidatorCfg;
import org.opends.server.admin.server.AdminTestCaseUtils;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Attribute;
@@ -316,8 +314,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -384,8 +383,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -450,9 +450,10 @@
new Attribute("userpassword", "pasSw")));
InternalClientConnection conn =
- InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ InternalClientConnection.getRootConnection();
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -519,8 +520,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -585,8 +587,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
@@ -652,8 +655,9 @@
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(),
+ conn.nextMessageID(),
new ArrayList<Control>(),
DN.decode("uid=test.user,o=test"), mods);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java
index b70acc7..3933296 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/internal/InternalClientConnectionTestCase.java
@@ -28,16 +28,18 @@
+import static org.opends.server.util.ServerConstants.OID_WHO_AM_I_REQUEST;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
import org.opends.server.TestCaseUtils;
-import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionSecurityProvider;
import org.opends.server.core.AddOperation;
import org.opends.server.core.BindOperation;
@@ -45,23 +47,23 @@
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ExtendedOperation;
-import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.ldap.LDAPAttribute;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.protocols.ldap.LDAPModification;
+import org.opends.server.types.AbstractOperation;
import org.opends.server.types.Attribute;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.CancelRequest;
import org.opends.server.types.CancelResult;
+import org.opends.server.types.DN;
import org.opends.server.types.DereferencePolicy;
import org.opends.server.types.DisconnectReason;
-import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
-import org.opends.server.types.Operation;
import org.opends.server.types.RawAttribute;
import org.opends.server.types.RawModification;
import org.opends.server.types.RDN;
@@ -69,10 +71,9 @@
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchResultReference;
import org.opends.server.types.SearchScope;
-
-import static org.testng.Assert.*;
-
-import static org.opends.server.util.ServerConstants.*;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
@@ -1068,7 +1069,7 @@
{
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
- Collection<Operation> opList = conn.getOperationsInProgress();
+ Collection<AbstractOperation> opList = conn.getOperationsInProgress();
assertNotNull(opList);
assertTrue(opList.isEmpty());
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxConnectTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxConnectTest.java
index 001c295..a2c57a4 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxConnectTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxConnectTest.java
@@ -51,8 +51,8 @@
import org.opends.server.admin.std.meta.JMXConnectionHandlerCfgDefn;
import org.opends.server.admin.std.server.JMXConnectionHandlerCfg;
import org.opends.server.config.JMXMBean;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.AddOperationBasis;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.ConfigChangeResult;
@@ -221,7 +221,7 @@
+ serverJmxPort, "cn: JMX Connection Handler");
InternalClientConnection connection =
InternalClientConnection.getRootConnection();
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(), null,
newJmxConnectionJmx.getDN(), newJmxConnectionJmx
@@ -259,7 +259,7 @@
// cleanup client connection
connector.close();
jmxcDisabled.close();
- DeleteOperation delOp = new DeleteOperation(connection,
+ DeleteOperationBasis delOp = new DeleteOperationBasis(connection,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(), null,
newJmxConnectionJmx.getDN());
@@ -588,4 +588,5 @@
mbsc.setAttribute(name, attr);
}
+
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxTestCase.java
index 7f9dcd8..d039bdf 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/jmx/JmxTestCase.java
@@ -35,7 +35,7 @@
import org.opends.server.TestCaseUtils;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.types.Control;
import org.opends.server.types.DN;
@@ -127,7 +127,7 @@
mods.add(new Modification(ModificationType.REPLACE,
new org.opends.server.types.Attribute(
"ds-cfg-connection-handler-enabled", "true")));
- ModifyOperation op = new ModifyOperation(
+ ModifyOperationBasis op = new ModifyOperationBasis(
conn,
conn.nextOperationID(),
conn.nextMessageID(),
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java
index 1d774fb..2f6f0c8 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java
@@ -26,11 +26,20 @@
*/
package org.opends.server.replication;
-import static org.opends.server.config.ConfigConstants.*;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_COMPLETION_TIME;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_INITIALIZE_DONE;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_INITIALIZE_LEFT;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_LOG_MESSAGES;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_STATE;
import static org.opends.server.loggers.ErrorLogger.logError;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.messages.ReplicationMessages.MSGID_INVALID_IMPORT_SOURCE;
+import static org.opends.server.messages.ReplicationMessages.MSGID_NO_MATCHING_DOMAIN;
+import static org.opends.server.messages.ReplicationMessages.MSGID_NO_REACHABLE_PEER_IN_THE_DOMAIN;
+import static org.opends.server.messages.ReplicationMessages.MSGID_SIMULTANEOUS_IMPORT_EXPORT_REJECTED;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@@ -42,7 +51,9 @@
import org.opends.server.TestCaseUtils;
import org.opends.server.backends.task.TaskState;
import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.messages.TaskMessages;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
@@ -53,11 +64,11 @@
import org.opends.server.replication.protocol.ErrorMessage;
import org.opends.server.replication.protocol.InitializeRequestMessage;
import org.opends.server.replication.protocol.InitializeTargetMessage;
+import org.opends.server.replication.protocol.ReplicationMessage;
import org.opends.server.replication.protocol.RoutableMessage;
import org.opends.server.replication.protocol.SocketSession;
-import org.opends.server.replication.protocol.ReplicationMessage;
-import org.opends.server.replication.server.ReplicationServer;
import org.opends.server.replication.server.ReplServerFakeConfiguration;
+import org.opends.server.replication.server.ReplicationServer;
import org.opends.server.schema.DirectoryStringSyntax;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
@@ -69,8 +80,6 @@
import org.opends.server.types.SearchScope;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-import static org.opends.server.messages.ReplicationMessages.*;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
/**
* Tests contained here:
@@ -564,7 +573,7 @@
for (String ldifEntry : updatedEntries)
{
Entry entry = TestCaseUtils.entryFromLdifString(ldifEntry);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java
index f6921f5..82e4e8c 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java
@@ -31,14 +31,13 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
-import java.io.IOException;
import java.net.ServerSocket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
import org.opends.server.TestCaseUtils;
-import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
import org.opends.server.protocols.asn1.ASN1OctetString;
@@ -115,7 +114,7 @@
// Create an Entry (add operation) that will be later used in the test.
Entry tmp = personEntry.duplicate(false);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, tmp.getDN(),
tmp.getObjectClasses(), tmp.getUserAttributes(),
@@ -255,7 +254,7 @@
for (int i = 0; i < topEntries.length; i++)
{
entry = TestCaseUtils.entryFromLdifString(topEntries[i]);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReSyncTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReSyncTest.java
index b6b76e1..9a46722 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReSyncTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReSyncTest.java
@@ -33,9 +33,8 @@
import java.util.UUID;
import org.opends.server.TestCaseUtils;
-import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
-
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.ResultCode;
@@ -123,14 +122,15 @@
private ResultCode addEntry(String entryString) throws Exception
{
Entry entry;
- AddOperation addOp;
+ AddOperationBasis addOp;
entry = TestCaseUtils.entryFromLdifString(entryString);
- addOp = new AddOperation(connection,
+ addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
addOp.setInternalOperation(true);
addOp.run();
+
entryList.add(entry.getDN());
return addOp.getResultCode();
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
index dfaa5eb..7ab93ba 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
@@ -31,52 +31,50 @@
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
-import java.util.NoSuchElementException;
import java.util.List;
+import java.util.NoSuchElementException;
import java.util.concurrent.locks.Lock;
import org.opends.server.DirectoryServerTestCase;
import org.opends.server.TestCaseUtils;
-import org.opends.server.replication.common.ServerState;
-import org.opends.server.replication.plugin.ReplicationBroker;
-import org.opends.server.replication.plugin.ReplicationDomain;
-import org.opends.server.replication.plugin.PersistentServerState;
-import org.opends.server.schema.DirectoryStringSyntax;
-import org.opends.server.schema.IntegerSyntax;
import org.opends.server.backends.task.TaskState;
import org.opends.server.core.AddOperation;
-import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.ldap.LDAPFilter;
+import org.opends.server.replication.common.ServerState;
+import org.opends.server.replication.plugin.PersistentServerState;
+import org.opends.server.replication.plugin.ReplicationBroker;
+import org.opends.server.schema.DirectoryStringSyntax;
+import org.opends.server.schema.IntegerSyntax;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.ByteStringFactory;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
-import org.opends.server.types.ByteStringFactory;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.LockManager;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SearchScope;
import org.opends.server.types.SearchResultEntry;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.LockManager;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeValue;
+import org.opends.server.types.SearchScope;
import org.opends.server.util.TimeThread;
import org.testng.annotations.AfterClass;
-import org.testng.annotations.Test;
-
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
/**
* An abstract class that all Replication unit test should extend.
@@ -254,7 +252,7 @@
ErrorLogSeverity.NOTICE,
"ReplicationTestCase/Cleaning config entries" , 1);
- DeleteOperation op;
+ DeleteOperationBasis op;
// Delete entries
try
{
@@ -265,10 +263,9 @@
ErrorLogSeverity.NOTICE,
"cleaning config entry " + dn, 1);
- op = new DeleteOperation(connection, InternalClientConnection
+ op = new DeleteOperationBasis(connection, InternalClientConnection
.nextOperationID(), InternalClientConnection.nextMessageID(), null,
dn);
-
op.run();
}
}
@@ -286,7 +283,7 @@
ErrorLogSeverity.NOTICE,
"ReplicationTestCase/Cleaning entries" , 1);
- DeleteOperation op;
+ DeleteOperationBasis op;
// Delete entries
try
{
@@ -297,7 +294,7 @@
ErrorLogSeverity.NOTICE,
"cleaning entry " + dn, 1);
- op = new DeleteOperation(connection, InternalClientConnection
+ op = new DeleteOperationBasis(connection, InternalClientConnection
.nextOperationID(), InternalClientConnection.nextMessageID(), null,
dn);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/SchemaReplicationTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/SchemaReplicationTest.java
index 8468f5a..0296bcd 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/SchemaReplicationTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/SchemaReplicationTest.java
@@ -42,6 +42,7 @@
import org.opends.server.api.SynchronizationProvider;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.plugin.ReplicationBroker;
@@ -149,7 +150,7 @@
List<Modification> mods = new ArrayList<Modification>();
Modification mod = new Modification(ModificationType.ADD, attr);
mods.add(mod);
- ModifyOperation modOp = new ModifyOperation(connection,
+ ModifyOperationBasis modOp = new ModifyOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, baseDn, mods);
modOp.setInternalOperation(true);
@@ -192,7 +193,7 @@
mod = new Modification(ModificationType.DELETE, attr);
mods.clear();
mods.add(mod);
- modOp = new ModifyOperation(connection,
+ modOp = new ModifyOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, baseDn, mods);
modOp.setInternalOperation(true);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/StressTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/StressTest.java
index 24b2f0d..6341c62 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/StressTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/StressTest.java
@@ -40,7 +40,7 @@
import org.opends.server.admin.std.server.MonitorProviderCfg;
import org.opends.server.api.MonitorProvider;
import org.opends.server.config.ConfigException;
-import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
import org.opends.server.protocols.internal.InternalClientConnection;
@@ -104,7 +104,7 @@
// Create an Entry (add operation) that will be later used in the test.
Entry tmp = personEntry.duplicate(false);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, tmp.getDN(),
tmp.getObjectClasses(), tmp.getUserAttributes(),
@@ -193,7 +193,7 @@
for (int i = 0; i < topEntries.length; i++)
{
entry = TestCaseUtils.entryFromLdifString(topEntries[i]);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
index 3b63fc5..c93ae7f 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
@@ -28,7 +28,12 @@
package org.opends.server.replication;
import static org.opends.server.loggers.ErrorLogger.logError;
-import static org.testng.Assert.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
import java.net.ServerSocket;
import java.util.ArrayList;
@@ -37,7 +42,17 @@
import java.util.concurrent.locks.Lock;
import org.opends.server.TestCaseUtils;
+import org.opends.server.core.AddOperationBasis;
+import org.opends.server.core.DeleteOperationBasis;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.plugins.ShortCircuitPlugin;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.ldap.LDAPAttribute;
+import org.opends.server.protocols.ldap.LDAPModification;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.plugin.ReplicationBroker;
@@ -49,16 +64,21 @@
import org.opends.server.replication.protocol.ModifyMsg;
import org.opends.server.replication.protocol.ReplicationMessage;
import org.opends.server.schema.DirectoryStringSyntax;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.DeleteOperation;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyDNOperation;
-import org.opends.server.core.ModifyOperation;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.internal.InternalClientConnection;
-import org.opends.server.protocols.ldap.LDAPAttribute;
-import org.opends.server.protocols.ldap.LDAPModification;
-import org.opends.server.types.*;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.ErrorLogCategory;
+import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.LockManager;
+import org.opends.server.types.Modification;
+import org.opends.server.types.ModificationType;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.RDN;
+import org.opends.server.types.RawModification;
+import org.opends.server.types.ResultCode;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -246,7 +266,7 @@
*/
private void addEntry(Entry entry) throws Exception
{
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
@@ -933,7 +953,7 @@
for (String entryStr : topEntries)
{
entry = TestCaseUtils.entryFromLdifString(entryStr);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
@@ -974,7 +994,7 @@
+ "objectClass: organizationalUnit\n"
+ "entryUUID: 66666666-6666-6666-6666-666666666666\n";
entry = TestCaseUtils.entryFromLdifString(p2);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
@@ -1122,7 +1142,7 @@
// Create an Entry (add operation)
Entry tmp = personEntry.duplicate(false);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, tmp.getDN(),
tmp.getObjectClasses(), tmp.getUserAttributes(),
@@ -1151,7 +1171,7 @@
// Modify the entry
List<Modification> mods = generatemods("telephonenumber", "01 02 45");
- ModifyOperation modOp = new ModifyOperation(connection,
+ ModifyOperationBasis modOp = new ModifyOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, personEntry.getDN(), mods);
modOp.setInternalOperation(true);
@@ -1191,7 +1211,7 @@
"The received MODIFY_DN message is not for the excepted DN");
// Delete the entry
- DeleteOperation delOp = new DeleteOperation(connection,
+ DeleteOperationBasis delOp = new DeleteOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, DN
.decode("uid= new person,ou=People,dc=example,dc=com"));
@@ -1357,8 +1377,8 @@
"Starting replication test : deleteNoSuchObject" , 1);
DN dn = DN.decode("cn=No Such Object,ou=People,dc=example,dc=com");
- Operation op =
- new DeleteOperation(connection,
+ DeleteOperationBasis op =
+ new DeleteOperationBasis(connection,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(), null,
dn);
@@ -1404,8 +1424,8 @@
+ "sn: Amar\n" + "givenName: Aaccf\n" + "postalCode: 85762\n"
+ "userPassword: password\n" + "initials: AA\n";
Entry tmp = TestCaseUtils.entryFromLdifString(personLdif);
- AddOperation addOp =
- new AddOperation(connection,
+ AddOperationBasis addOp =
+ new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(),
InternalClientConnection.nextMessageID(),
null, tmp.getDN(), tmp.getObjectClasses(),
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ModifyConflictTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ModifyConflictTest.java
index ef37b40..15c2203 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ModifyConflictTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ModifyConflictTest.java
@@ -39,8 +39,9 @@
import static org.opends.server.replication.protocol.OperationContext.*;
import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.ReplicationTestCase;
@@ -693,7 +694,7 @@
List<Modification> mods = new ArrayList<Modification>();
mods.add(mod);
- ModifyOperation modOp = new ModifyOperation(connection, 1, 1, null,
+ ModifyOperationBasis modOp = new ModifyOperationBasis(connection, 1, 1, null,
entry.getDN(), mods);
ModifyContext ctx = new ModifyContext(t, "uniqueId");
modOp.setAttachment(SYNCHROCONTEXT, ctx);
@@ -701,7 +702,7 @@
hist.replayOperation(modOp, entry);
if (mod.getModificationType() == ModificationType.ADD)
{
- AddOperation addOp = new AddOperation(connection, 1, 1, null, entry
+ AddOperationBasis addOp = new AddOperationBasis(connection, 1, 1, null, entry
.getDN(), entry.getObjectClasses(), entry.getUserAttributes(),
entry.getOperationalAttributes());
testHistorical(hist, addOp);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentServerStateTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentServerStateTest.java
index 83e65a0..f461e1f 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentServerStateTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentServerStateTest.java
@@ -29,12 +29,11 @@
import static org.testng.Assert.assertEquals;
import org.opends.server.TestCaseUtils;
-import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ChangeNumberGenerator;
-import org.opends.server.replication.plugin.PersistentServerState;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.testng.annotations.BeforeClass;
@@ -65,7 +64,7 @@
connection = InternalClientConnection.getRootConnection();
Entry entry = TestCaseUtils.entryFromLdifString(topEntry);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentStateTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentStateTest.java
index d39d45f..6206ecf 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentStateTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentStateTest.java
@@ -29,12 +29,11 @@
import static org.testng.Assert.assertEquals;
import org.opends.server.TestCaseUtils;
-import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ChangeNumberGenerator;
-import org.opends.server.replication.plugin.PersistentServerState;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.testng.annotations.BeforeClass;
@@ -65,7 +64,7 @@
connection = InternalClientConnection.getRootConnection();
Entry entry = TestCaseUtils.entryFromLdifString(topEntry);
- AddOperation addOp = new AddOperation(connection,
+ AddOperationBasis addOp = new AddOperationBasis(connection,
InternalClientConnection.nextOperationID(), InternalClientConnection
.nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
entry.getUserAttributes(), entry.getOperationalAttributes());
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
index f51c762..bd48b77 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/protocol/SynchronizationMsgTest.java
@@ -40,10 +40,11 @@
import java.util.zip.DataFormatException;
import org.opends.server.core.AddOperation;
-import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.AddOperationBasis;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyDNOperation;
-import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.common.ChangeNumber;
@@ -175,11 +176,11 @@
Operation op = msg.createOperation(connection);
Operation generatedOperation = generatedMsg.createOperation(connection);
- assertEquals(op.getClass(), ModifyOperation.class);
- assertEquals(generatedOperation.getClass(), ModifyOperation.class);
+ assertEquals(op.getClass(), ModifyOperationBasis.class);
+ assertEquals(generatedOperation.getClass(), ModifyOperationBasis.class);
- ModifyOperation mod1 = (ModifyOperation) op;
- ModifyOperation mod2 = (ModifyOperation) generatedOperation;
+ ModifyOperationBasis mod1 = (ModifyOperationBasis) op;
+ ModifyOperationBasis mod2 = (ModifyOperationBasis) generatedOperation;
assertEquals(mod1.getRawEntryDN(), mod2.getRawEntryDN());
assertEquals( mod1.getAttachment(SYNCHROCONTEXT),
@@ -259,7 +260,7 @@
{
InternalClientConnection connection =
InternalClientConnection.getRootConnection();
- DeleteOperation op = new DeleteOperation(connection, 1, 1,null,
+ DeleteOperationBasis op = new DeleteOperationBasis(connection, 1, 1,null,
DN.decode(rawDN));
ChangeNumber cn = new ChangeNumber(TimeThread.getTime(),
(short) 123, (short) 45);
@@ -274,9 +275,9 @@
Operation generatedOperation = generatedMsg.createOperation(connection);
- assertEquals(generatedOperation.getClass(), DeleteOperation.class);
+ assertEquals(generatedOperation.getClass(), DeleteOperationBasis.class);
- DeleteOperation mod2 = (DeleteOperation) generatedOperation;
+ DeleteOperationBasis mod2 = (DeleteOperationBasis) generatedOperation;
assertEquals(op.getRawEntryDN(), mod2.getRawEntryDN());
@@ -402,7 +403,7 @@
//Create an Add operation and generate and Add msg from it
DN dn = DN.decode(rawDN);
- addOp = new AddOperation(connection,
+ addOp = new AddOperationBasis(connection,
(long) 1, 1, null, dn, objectClassList, userAttList, opList);
OperationContext opCtx = new AddContext(cn, "thisIsaUniqueID",
"parentUniqueId");
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/UpdateComparatorTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/UpdateComparatorTest.java
index cc57d13..a287160 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/UpdateComparatorTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/UpdateComparatorTest.java
@@ -34,6 +34,7 @@
import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.common.ChangeNumber;
@@ -70,7 +71,7 @@
DeleteOperation op = null;
try
{
- op = new DeleteOperation(connection, 1, 1,null,
+ op = new DeleteOperationBasis(connection, 1, 1,null,
DN.decode("dc=com"));
}
catch (DirectoryException e)
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
index fa60bcf..bdd0828 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
@@ -28,30 +28,32 @@
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.UUID;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
import org.opends.server.TestCaseUtils;
-import static org.opends.server.util.StaticUtils.createEntry;
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskBackend;
import org.opends.server.backends.task.TaskState;
import org.opends.server.controls.ProxiedAuthV1Control;
import org.opends.server.controls.ProxiedAuthV2Control;
import org.opends.server.core.AddOperation;
+import org.opends.server.core.AddOperationBasis;
import org.opends.server.core.CompareOperation;
import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DeleteOperationBasis;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.core.SchemaConfigManager;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.internal.InternalClientConnection;
@@ -59,16 +61,10 @@
import org.opends.server.tools.LDAPModify;
import org.opends.server.tools.LDAPPasswordModify;
import org.opends.server.tools.LDAPSearch;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AuthenticationInfo;
-import org.opends.server.types.DN;
-import org.opends.server.types.Modification;
-import org.opends.server.types.ModificationType;
-import org.opends.server.types.RDN;
-import org.opends.server.types.SearchFilter;
-import org.opends.server.types.SearchScope;
-
-import static org.testng.Assert.*;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
@@ -1177,8 +1173,8 @@
// Try to add the entry. If this fails with the proxy control, then add it
// with a root connection so we can do other things with it.
- AddOperation addOperation =
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, e.getDN(), e.getObjectClasses(),
e.getUserAttributes(), e.getOperationalAttributes());
addOperation.run();
@@ -1200,8 +1196,8 @@
mods.add(new Modification(ModificationType.REPLACE,
new Attribute("description", "foo")));
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, e.getDN(), mods);
modifyOperation.run();
@@ -1239,8 +1235,8 @@
// Try to delete the operation. If this fails, then delete it with a root
// connection so it gets cleaned up.
- DeleteOperation deleteOperation =
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ DeleteOperationBasis deleteOperation =
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, newEntryDN);
deleteOperation.run();
@@ -1255,8 +1251,8 @@
InternalClientConnection rootConnection =
InternalClientConnection.getRootConnection();
- deleteOperation = rootConnection.processDelete(newEntryDN);
- assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ DeleteOperation delOp = rootConnection.processDelete(newEntryDN);
+ assertEquals(delOp.getResultCode(), ResultCode.SUCCESS);
}
}
@@ -1373,8 +1369,8 @@
// Try to add the entry. If this fails with the proxy control, then add it
// with a root connection so we can do other things with it.
DN authDN = conn.getAuthenticationInfo().getAuthenticationDN();
- AddOperation addOperation =
- new AddOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ AddOperationBasis addOperation =
+ new AddOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, e.getDN(), e.getObjectClasses(),
e.getUserAttributes(), e.getOperationalAttributes());
addOperation.run();
@@ -1398,8 +1394,8 @@
mods.add(new Modification(ModificationType.REPLACE,
new Attribute("description", "foo")));
- ModifyOperation modifyOperation =
- new ModifyOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ ModifyOperationBasis modifyOperation =
+ new ModifyOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, e.getDN(), mods);
modifyOperation.run();
@@ -1441,8 +1437,8 @@
// Try to delete the operation. If this fails, then delete it with a root
// connection so it gets cleaned up.
- DeleteOperation deleteOperation =
- new DeleteOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
+ DeleteOperationBasis deleteOperation =
+ new DeleteOperationBasis(conn, conn.nextOperationID(), conn.nextMessageID(),
controls, newEntryDN);
deleteOperation.run();
@@ -1459,8 +1455,8 @@
InternalClientConnection rootConnection =
InternalClientConnection.getRootConnection();
- deleteOperation = rootConnection.processDelete(newEntryDN);
- assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ DeleteOperation delOp = rootConnection.processDelete(newEntryDN);
+ assertEquals(delOp.getResultCode(), ResultCode.SUCCESS);
}
}
--
Gitblit v1.10.0