From fbda6e0892dcfcc8dd43d21f6fb134aabb8d0cac 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.
---
opends/src/server/org/opends/server/core/SearchOperation.java | 2310 +++++------------------------------------------------------
1 files changed, 197 insertions(+), 2,113 deletions(-)
diff --git a/opends/src/server/org/opends/server/core/SearchOperation.java b/opends/src/server/org/opends/server/core/SearchOperation.java
index 007fd1d..80fb4fa 100644
--- a/opends/src/server/org/opends/server/core/SearchOperation.java
+++ b/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
--
Gitblit v1.10.0