Search in sources :

Example 1 with ReadOnlyEntry

use of com.unboundid.ldap.sdk.ReadOnlyEntry in project ldapsdk by pingidentity.

the class InMemoryRequestHandler method processModifyDNRequest.

/**
 * Attempts to process the provided modify DN request.  The attempt will fail
 * if any of the following conditions is true:
 * <UL>
 *   <LI>There is a problem with any of the request controls.</LI>
 *   <LI>The modify DN request contains a malformed target DN, new RDN, or
 *       new superior DN.</LI>
 *   <LI>The original or new DN is that of the root DSE.</LI>
 *   <LI>The original or new DN is that of the subschema subentry.</LI>
 *   <LI>The new DN of the entry would conflict with the DN of an existing
 *       entry.</LI>
 *   <LI>The new DN of the entry would exist outside the set of defined
 *       base DNs.</LI>
 *   <LI>The new DN of the entry is not a defined base DN and does not exist
 *       immediately below an existing entry.</LI>
 * </UL>
 *
 * @param  messageID  The message ID of the LDAP message containing the modify
 *                    DN request.
 * @param  request    The modify DN request that was included in the LDAP
 *                    message that was received.
 * @param  controls   The set of controls included in the LDAP message.  It
 *                    may be empty if there were no controls, but will not be
 *                    {@code null}.
 *
 * @return  The {@link LDAPMessage} containing the response to send to the
 *          client.  The protocol op in the {@code LDAPMessage} must be an
 *          {@code ModifyDNResponseProtocolOp}.
 */
@Override()
@NotNull()
public LDAPMessage processModifyDNRequest(final int messageID, @NotNull final ModifyDNRequestProtocolOp request, @NotNull final List<Control> controls) {
    synchronized (entryMap) {
        // Sleep before processing, if appropriate.
        sleepBeforeProcessing();
        // Process the provided request controls.
        final Map<String, Control> controlMap;
        try {
            controlMap = RequestControlPreProcessor.processControls(LDAPMessage.PROTOCOL_OP_TYPE_MODIFY_DN_REQUEST, controls);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null));
        }
        final ArrayList<Control> responseControls = new ArrayList<>(1);
        // If this operation type is not allowed, then reject it.
        final boolean isInternalOp = controlMap.containsKey(OID_INTERNAL_OPERATION_REQUEST_CONTROL);
        if ((!isInternalOp) && (!config.getAllowedOperationTypes().contains(OperationType.MODIFY_DN))) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_MODIFY_DN_NOT_ALLOWED.get(), null));
        }
        // client is authenticated.
        if ((authenticatedDN.isNullDN() && config.getAuthenticationRequiredOperationTypes().contains(OperationType.MODIFY_DN))) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.INSUFFICIENT_ACCESS_RIGHTS_INT_VALUE, null, ERR_MEM_HANDLER_MODIFY_DN_REQUIRES_AUTH.get(), null));
        }
        // without actually doing any further processing.
        try {
            final ASN1OctetString txnID = processTransactionRequest(messageID, request, controlMap);
            if (txnID != null) {
                return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, INFO_MEM_HANDLER_OP_IN_TXN.get(txnID.stringValue()), null));
            }
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(le.getResultCode().intValue(), le.getMatchedDN(), le.getDiagnosticMessage(), StaticUtils.toList(le.getReferralURLs())), le.getResponseControls());
        }
        // Get the parsed target DN, new RDN, and new superior DN values.
        final DN dn;
        final Schema schema = schemaRef.get();
        try {
            dn = new DN(request.getDN(), schema);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.INVALID_DN_SYNTAX_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_MALFORMED_DN.get(request.getDN(), le.getMessage()), null));
        }
        final RDN newRDN;
        try {
            newRDN = new RDN(request.getNewRDN(), schema);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.INVALID_DN_SYNTAX_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_MALFORMED_NEW_RDN.get(request.getDN(), request.getNewRDN(), le.getMessage()), null));
        }
        final DN newSuperiorDN;
        final String newSuperiorString = request.getNewSuperiorDN();
        if (newSuperiorString == null) {
            newSuperiorDN = null;
        } else {
            try {
                newSuperiorDN = new DN(newSuperiorString, schema);
            } catch (final LDAPException le) {
                Debug.debugException(le);
                return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.INVALID_DN_SYNTAX_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_MALFORMED_NEW_SUPERIOR.get(request.getDN(), request.getNewSuperiorDN(), le.getMessage()), null));
            }
        }
        // See if the target entry or one of its superiors is a smart referral.
        if (!controlMap.containsKey(ManageDsaITRequestControl.MANAGE_DSA_IT_REQUEST_OID)) {
            final Entry referralEntry = findNearestReferral(dn);
            if (referralEntry != null) {
                return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.REFERRAL_INT_VALUE, referralEntry.getDN(), INFO_MEM_HANDLER_REFERRAL_ENCOUNTERED.get(), getReferralURLs(dn, referralEntry)));
            }
        }
        // changelog entry.
        if (dn.isNullDN()) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_ROOT_DSE.get(), null));
        } else if (dn.equals(subschemaSubentryDN)) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_SOURCE_IS_SCHEMA.get(), null));
        } else if (dn.isDescendantOf(changeLogBaseDN, true)) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_SOURCE_IS_CHANGELOG.get(), null));
        }
        // Construct the new DN.
        final DN newDN;
        if (newSuperiorDN == null) {
            final DN originalParent = dn.getParent();
            if (originalParent == null) {
                newDN = new DN(newRDN);
            } else {
                newDN = new DN(newRDN, originalParent);
            }
        } else {
            newDN = new DN(newRDN, newSuperiorDN);
        }
        // If the new DN matches the old DN, then fail.
        if (newDN.equals(dn)) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_NEW_DN_SAME_AS_OLD.get(request.getDN()), null));
        }
        // If the new DN is below a smart referral, then fail.
        if (!controlMap.containsKey(ManageDsaITRequestControl.MANAGE_DSA_IT_REQUEST_OID)) {
            final Entry referralEntry = findNearestReferral(newDN);
            if (referralEntry != null) {
                return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, referralEntry.getDN(), ERR_MEM_HANDLER_MOD_DN_NEW_DN_BELOW_REFERRAL.get(request.getDN(), referralEntry.getDN().toString(), newDN.toString()), null));
            }
        }
        // If the target entry doesn't exist, then fail.
        final Entry originalEntry = entryMap.get(dn);
        if (originalEntry == null) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.NO_SUCH_OBJECT_INT_VALUE, getMatchedDNString(dn), ERR_MEM_HANDLER_MOD_DN_NO_SUCH_ENTRY.get(request.getDN()), null));
        }
        // If the new DN matches the subschema subentry DN, then fail.
        if (newDN.equals(subschemaSubentryDN)) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.ENTRY_ALREADY_EXISTS_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_TARGET_IS_SCHEMA.get(request.getDN(), newDN.toString()), null));
        }
        // If the new DN is at or below the changelog base DN, then fail.
        if (newDN.isDescendantOf(changeLogBaseDN, true)) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_TARGET_IS_CHANGELOG.get(request.getDN(), newDN.toString()), null));
        }
        // If the new DN already exists, then fail.
        if (entryMap.containsKey(newDN)) {
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.ENTRY_ALREADY_EXISTS_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_TARGET_ALREADY_EXISTS.get(request.getDN(), newDN.toString()), null));
        }
        // fail.
        if (baseDNs.contains(newDN)) {
        // The modify DN can be processed.
        } else {
            final DN newParent = newDN.getParent();
            if ((newParent != null) && entryMap.containsKey(newParent)) {
            // The modify DN can be processed.
            } else {
                return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.NO_SUCH_OBJECT_INT_VALUE, getMatchedDNString(newDN), ERR_MEM_HANDLER_MOD_DN_PARENT_DOESNT_EXIST.get(request.getDN(), newDN.toString()), null));
            }
        }
        // Create a copy of the entry and update it to reflect the new DN (with
        // attribute value changes).
        final RDN originalRDN = dn.getRDN();
        final Entry updatedEntry = originalEntry.duplicate();
        updatedEntry.setDN(newDN);
        if (request.deleteOldRDN()) {
            final String[] oldRDNNames = originalRDN.getAttributeNames();
            final byte[][] oldRDNValues = originalRDN.getByteArrayAttributeValues();
            for (int i = 0; i < oldRDNNames.length; i++) {
                updatedEntry.removeAttributeValue(oldRDNNames[i], oldRDNValues[i]);
            }
        }
        final String[] newRDNNames = newRDN.getAttributeNames();
        final byte[][] newRDNValues = newRDN.getByteArrayAttributeValues();
        for (int i = 0; i < newRDNNames.length; i++) {
            final MatchingRule matchingRule = MatchingRule.selectEqualityMatchingRule(newRDNNames[i], schema);
            updatedEntry.addAttribute(new Attribute(newRDNNames[i], matchingRule, newRDNValues[i]));
        }
        // If a schema was provided, then make sure the updated entry conforms to
        // the schema.  Also, reject the attempt if any of the new RDN attributes
        // is marked with NO-USER-MODIFICATION.
        final EntryValidator entryValidator = entryValidatorRef.get();
        if (entryValidator != null) {
            final ArrayList<String> invalidReasons = new ArrayList<>(1);
            if (!entryValidator.entryIsValid(updatedEntry, invalidReasons)) {
                return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.OBJECT_CLASS_VIOLATION_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_VIOLATES_SCHEMA.get(request.getDN(), StaticUtils.concatenateStrings(invalidReasons)), null));
            }
            final String[] oldRDNNames = originalRDN.getAttributeNames();
            for (int i = 0; i < oldRDNNames.length; i++) {
                final String name = oldRDNNames[i];
                final AttributeTypeDefinition at = schema.getAttributeType(name);
                if ((!isInternalOp) && (at != null) && at.isNoUserModification()) {
                    final byte[] value = originalRDN.getByteArrayAttributeValues()[i];
                    if (!updatedEntry.hasAttributeValue(name, value)) {
                        return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.CONSTRAINT_VIOLATION_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_NO_USER_MOD.get(request.getDN(), name), null));
                    }
                }
            }
            for (int i = 0; i < newRDNNames.length; i++) {
                final String name = newRDNNames[i];
                final AttributeTypeDefinition at = schema.getAttributeType(name);
                if ((!isInternalOp) && (at != null) && at.isNoUserModification()) {
                    final byte[] value = newRDN.getByteArrayAttributeValues()[i];
                    if (!originalEntry.hasAttributeValue(name, value)) {
                        return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.CONSTRAINT_VIOLATION_INT_VALUE, null, ERR_MEM_HANDLER_MOD_DN_NO_USER_MOD.get(request.getDN(), name), null));
                    }
                }
            }
        }
        // Perform the appropriate processing for the assertion and proxied
        // authorization controls
        final DN authzDN;
        try {
            handleAssertionRequestControl(controlMap, originalEntry);
            authzDN = handleProxiedAuthControl(controlMap);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null));
        }
        // attributes.
        if (generateOperationalAttributes) {
            updatedEntry.setAttribute(new Attribute("modifiersName", DistinguishedNameMatchingRule.getInstance(), authzDN.toString()));
            updatedEntry.setAttribute(new Attribute("modifyTimestamp", GeneralizedTimeMatchingRule.getInstance(), StaticUtils.encodeGeneralizedTime(new Date())));
            updatedEntry.setAttribute(new Attribute("entryDN", DistinguishedNameMatchingRule.getInstance(), newDN.toNormalizedString()));
        }
        // Perform the appropriate processing for the pre-read and post-read
        // controls.
        final PreReadResponseControl preReadResponse = handlePreReadControl(controlMap, originalEntry);
        if (preReadResponse != null) {
            responseControls.add(preReadResponse);
        }
        final PostReadResponseControl postReadResponse = handlePostReadControl(controlMap, updatedEntry);
        if (postReadResponse != null) {
            responseControls.add(postReadResponse);
        }
        // Remove the old entry and add the new one.
        entryMap.remove(dn);
        entryMap.put(newDN, new ReadOnlyEntry(updatedEntry));
        indexDelete(originalEntry);
        indexAdd(updatedEntry);
        // If the target entry had any subordinates, then rename them as well.
        final RDN[] oldDNComps = dn.getRDNs();
        final RDN[] newDNComps = newDN.getRDNs();
        final Set<DN> dnSet = new LinkedHashSet<>(entryMap.keySet());
        for (final DN mapEntryDN : dnSet) {
            if (mapEntryDN.isDescendantOf(dn, false)) {
                final Entry o = entryMap.remove(mapEntryDN);
                final Entry e = o.duplicate();
                final RDN[] oldMapEntryComps = mapEntryDN.getRDNs();
                final int compsToSave = oldMapEntryComps.length - oldDNComps.length;
                final RDN[] newMapEntryComps = new RDN[compsToSave + newDNComps.length];
                System.arraycopy(oldMapEntryComps, 0, newMapEntryComps, 0, compsToSave);
                System.arraycopy(newDNComps, 0, newMapEntryComps, compsToSave, newDNComps.length);
                final DN newMapEntryDN = new DN(newMapEntryComps);
                e.setDN(newMapEntryDN);
                if (generateOperationalAttributes) {
                    e.setAttribute(new Attribute("entryDN", DistinguishedNameMatchingRule.getInstance(), newMapEntryDN.toNormalizedString()));
                }
                entryMap.put(newMapEntryDN, new ReadOnlyEntry(e));
                indexDelete(o);
                indexAdd(e);
                handleReferentialIntegrityModifyDN(mapEntryDN, newMapEntryDN);
            }
        }
        addChangeLogEntry(request, authzDN);
        handleReferentialIntegrityModifyDN(dn, newDN);
        return new LDAPMessage(messageID, new ModifyDNResponseProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null), responseControls);
    }
}
Also used : ASN1OctetString(com.unboundid.asn1.ASN1OctetString) LinkedHashSet(java.util.LinkedHashSet) Attribute(com.unboundid.ldap.sdk.Attribute) Schema(com.unboundid.ldap.sdk.schema.Schema) ArrayList(java.util.ArrayList) ModifyDNResponseProtocolOp(com.unboundid.ldap.protocol.ModifyDNResponseProtocolOp) RDN(com.unboundid.ldap.sdk.RDN) DN(com.unboundid.ldap.sdk.DN) ASN1OctetString(com.unboundid.asn1.ASN1OctetString) EntryValidator(com.unboundid.ldap.sdk.schema.EntryValidator) AttributeTypeDefinition(com.unboundid.ldap.sdk.schema.AttributeTypeDefinition) VirtualListViewRequestControl(com.unboundid.ldap.sdk.controls.VirtualListViewRequestControl) SubtreeDeleteRequestControl(com.unboundid.ldap.sdk.controls.SubtreeDeleteRequestControl) RFC3672SubentriesRequestControl(com.unboundid.ldap.sdk.controls.RFC3672SubentriesRequestControl) SimplePagedResultsControl(com.unboundid.ldap.sdk.controls.SimplePagedResultsControl) VirtualListViewResponseControl(com.unboundid.ldap.sdk.controls.VirtualListViewResponseControl) TransactionSpecificationRequestControl(com.unboundid.ldap.sdk.controls.TransactionSpecificationRequestControl) DraftZeilengaLDAPNoOp12RequestControl(com.unboundid.ldap.sdk.experimental.DraftZeilengaLDAPNoOp12RequestControl) PostReadRequestControl(com.unboundid.ldap.sdk.controls.PostReadRequestControl) ProxiedAuthorizationV1RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV1RequestControl) ServerSideSortResponseControl(com.unboundid.ldap.sdk.controls.ServerSideSortResponseControl) PreReadResponseControl(com.unboundid.ldap.sdk.controls.PreReadResponseControl) AuthorizationIdentityResponseControl(com.unboundid.ldap.sdk.controls.AuthorizationIdentityResponseControl) PermissiveModifyRequestControl(com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl) AuthorizationIdentityRequestControl(com.unboundid.ldap.sdk.controls.AuthorizationIdentityRequestControl) Control(com.unboundid.ldap.sdk.Control) IgnoreNoUserModificationRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.IgnoreNoUserModificationRequestControl) ProxiedAuthorizationV2RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl) ServerSideSortRequestControl(com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl) PostReadResponseControl(com.unboundid.ldap.sdk.controls.PostReadResponseControl) DontUseCopyRequestControl(com.unboundid.ldap.sdk.controls.DontUseCopyRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl) DraftLDUPSubentriesRequestControl(com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl) PreReadRequestControl(com.unboundid.ldap.sdk.controls.PreReadRequestControl) ChangeLogEntry(com.unboundid.ldap.sdk.ChangeLogEntry) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) Entry(com.unboundid.ldap.sdk.Entry) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) PostReadResponseControl(com.unboundid.ldap.sdk.controls.PostReadResponseControl) RDN(com.unboundid.ldap.sdk.RDN) LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) Date(java.util.Date) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) LDAPException(com.unboundid.ldap.sdk.LDAPException) PreReadResponseControl(com.unboundid.ldap.sdk.controls.PreReadResponseControl) IntegerMatchingRule(com.unboundid.ldap.matchingrules.IntegerMatchingRule) DistinguishedNameMatchingRule(com.unboundid.ldap.matchingrules.DistinguishedNameMatchingRule) MatchingRule(com.unboundid.ldap.matchingrules.MatchingRule) GeneralizedTimeMatchingRule(com.unboundid.ldap.matchingrules.GeneralizedTimeMatchingRule) NotNull(com.unboundid.util.NotNull)

Example 2 with ReadOnlyEntry

use of com.unboundid.ldap.sdk.ReadOnlyEntry in project ldapsdk by pingidentity.

the class InMemoryRequestHandler method handlePreReadControl.

/**
 * Checks to see if the provided control map includes a pre-read request
 * control, and if so then generates the appropriate response control that
 * should be returned to the client.
 *
 * @param  m  The map of request controls, indexed by OID.
 * @param  e  The entry as it appeared before the operation.
 *
 * @return  The pre-read response control that should be returned to the
 *          client, or {@code null} if there is none.
 */
@Nullable()
private PreReadResponseControl handlePreReadControl(@NotNull final Map<String, Control> m, @NotNull final Entry e) {
    final PreReadRequestControl c = (PreReadRequestControl) m.get(PreReadRequestControl.PRE_READ_REQUEST_OID);
    if (c == null) {
        return null;
    }
    final SearchEntryParer parer = new SearchEntryParer(Arrays.asList(c.getAttributes()), schemaRef.get());
    final Entry trimmedEntry = parer.pareEntry(e);
    return new PreReadResponseControl(new ReadOnlyEntry(trimmedEntry));
}
Also used : ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) ChangeLogEntry(com.unboundid.ldap.sdk.ChangeLogEntry) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) Entry(com.unboundid.ldap.sdk.Entry) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) PreReadResponseControl(com.unboundid.ldap.sdk.controls.PreReadResponseControl) PreReadRequestControl(com.unboundid.ldap.sdk.controls.PreReadRequestControl) Nullable(com.unboundid.util.Nullable)

Example 3 with ReadOnlyEntry

use of com.unboundid.ldap.sdk.ReadOnlyEntry in project ldapsdk by pingidentity.

the class InMemoryRequestHandler method processSearchRequest.

/**
 * Attempts to process the provided search request.  The attempt will fail
 * if any of the following conditions is true:
 * <UL>
 *   <LI>There is a problem with any of the request controls.</LI>
 *   <LI>The modify DN request contains a malformed target DN, new RDN, or
 *       new superior DN.</LI>
 *   <LI>The new DN of the entry would conflict with the DN of an existing
 *       entry.</LI>
 *   <LI>The new DN of the entry would exist outside the set of defined
 *       base DNs.</LI>
 *   <LI>The new DN of the entry is not a defined base DN and does not exist
 *       immediately below an existing entry.</LI>
 * </UL>
 *
 * @param  messageID      The message ID of the LDAP message containing the
 *                        search request.
 * @param  request        The search request that was included in the LDAP
 *                        message that was received.
 * @param  controls       The set of controls included in the LDAP message.
 *                        It may be empty if there were no controls, but will
 *                        not be {@code null}.
 * @param  entryList      A list to which to add search result entries
 *                        intended for return to the client.  It must not be
 *                        {@code null}.
 * @param  referenceList  A list to which to add search result references
 *                        intended for return to the client.  It must not be
 *                        {@code null}.
 *
 * @return  The {@link LDAPMessage} containing the response to send to the
 *          client.  The protocol op in the {@code LDAPMessage} must be an
 *          {@code SearchResultDoneProtocolOp}.
 */
@NotNull()
LDAPMessage processSearchRequest(final int messageID, @NotNull final SearchRequestProtocolOp request, @NotNull final List<Control> controls, @NotNull final List<SearchResultEntry> entryList, @NotNull final List<SearchResultReference> referenceList) {
    synchronized (entryMap) {
        // Sleep before processing, if appropriate.
        final long processingStartTime = System.currentTimeMillis();
        sleepBeforeProcessing();
        // Look at the filter and see if it contains any unsupported elements.
        try {
            ensureFilterSupported(request.getFilter());
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null));
        }
        // Look at the time limit for the search request and see if sleeping
        // would have caused us to exceed that time limit.  It's extremely
        // unlikely that any search in the in-memory directory server would take
        // a second or more to complete, and that's the minimum time limit that
        // can be requested, so there's no need to check the time limit in most
        // cases.  However, someone may want to force a "time limit exceeded"
        // response by configuring a delay that is greater than the requested time
        // limit, so we should check now to see if that's been exceeded.
        final long timeLimitMillis = 1000L * request.getTimeLimit();
        if (timeLimitMillis > 0L) {
            final long timeLimitExpirationTime = processingStartTime + timeLimitMillis;
            if (System.currentTimeMillis() >= timeLimitExpirationTime) {
                return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.TIME_LIMIT_EXCEEDED_INT_VALUE, null, ERR_MEM_HANDLER_TIME_LIMIT_EXCEEDED.get(), null));
            }
        }
        // Process the provided request controls.
        final Map<String, Control> controlMap;
        try {
            controlMap = RequestControlPreProcessor.processControls(LDAPMessage.PROTOCOL_OP_TYPE_SEARCH_REQUEST, controls);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null));
        }
        final ArrayList<Control> responseControls = new ArrayList<>(1);
        // If this operation type is not allowed, then reject it.
        final boolean isInternalOp = controlMap.containsKey(OID_INTERNAL_OPERATION_REQUEST_CONTROL);
        if ((!isInternalOp) && (!config.getAllowedOperationTypes().contains(OperationType.SEARCH))) {
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.UNWILLING_TO_PERFORM_INT_VALUE, null, ERR_MEM_HANDLER_SEARCH_NOT_ALLOWED.get(), null));
        }
        // client is authenticated.
        if ((authenticatedDN.isNullDN() && config.getAuthenticationRequiredOperationTypes().contains(OperationType.SEARCH))) {
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.INSUFFICIENT_ACCESS_RIGHTS_INT_VALUE, null, ERR_MEM_HANDLER_SEARCH_REQUIRES_AUTH.get(), null));
        }
        // Get the parsed base DN.
        final DN baseDN;
        final Schema schema = schemaRef.get();
        try {
            baseDN = new DN(request.getBaseDN(), schema);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.INVALID_DN_SYNTAX_INT_VALUE, null, ERR_MEM_HANDLER_SEARCH_MALFORMED_BASE.get(request.getBaseDN(), le.getMessage()), null));
        }
        // See if the search base or one of its superiors is a smart referral.
        final boolean hasManageDsaIT = controlMap.containsKey(ManageDsaITRequestControl.MANAGE_DSA_IT_REQUEST_OID);
        if (!hasManageDsaIT) {
            final Entry referralEntry = findNearestReferral(baseDN);
            if (referralEntry != null) {
                return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.REFERRAL_INT_VALUE, referralEntry.getDN(), INFO_MEM_HANDLER_REFERRAL_ENCOUNTERED.get(), getReferralURLs(baseDN, referralEntry)));
            }
        }
        // Make sure that the base entry exists.  It may be the root DSE or
        // subschema subentry.
        final Entry baseEntry;
        boolean includeChangeLog = true;
        if (baseDN.isNullDN()) {
            baseEntry = generateRootDSE();
            includeChangeLog = false;
        } else if (baseDN.equals(subschemaSubentryDN)) {
            baseEntry = subschemaSubentryRef.get();
        } else {
            baseEntry = entryMap.get(baseDN);
        }
        if (baseEntry == null) {
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.NO_SUCH_OBJECT_INT_VALUE, getMatchedDNString(baseDN), ERR_MEM_HANDLER_SEARCH_BASE_DOES_NOT_EXIST.get(request.getBaseDN()), null));
        }
        // controls.
        try {
            handleAssertionRequestControl(controlMap, baseEntry);
            handleProxiedAuthControl(controlMap);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(le.getResultCode().intValue(), null, le.getMessage(), null));
        }
        // Determine whether to include subentries in search results.
        final boolean includeSubEntries;
        final boolean includeNonSubEntries;
        final SearchScope scope = request.getScope();
        if (scope == SearchScope.BASE) {
            includeSubEntries = true;
            includeNonSubEntries = true;
        } else if (controlMap.containsKey(DraftLDUPSubentriesRequestControl.SUBENTRIES_REQUEST_OID)) {
            includeSubEntries = true;
            includeNonSubEntries = false;
        } else if (controlMap.containsKey(RFC3672SubentriesRequestControl.SUBENTRIES_REQUEST_OID)) {
            includeSubEntries = true;
            final RFC3672SubentriesRequestControl c = (RFC3672SubentriesRequestControl) controlMap.get(RFC3672SubentriesRequestControl.SUBENTRIES_REQUEST_OID);
            includeNonSubEntries = (!c.returnOnlySubEntries());
        } else if (baseEntry.hasObjectClass("ldapSubEntry") || baseEntry.hasObjectClass("inheritableLDAPSubEntry")) {
            includeSubEntries = true;
            includeNonSubEntries = true;
        } else if (filterIncludesLDAPSubEntry(request.getFilter())) {
            includeSubEntries = true;
            includeNonSubEntries = true;
        } else {
            includeSubEntries = false;
            includeNonSubEntries = true;
        }
        // Create a temporary list to hold all of the entries to be returned.
        // These entries will not have been pared down based on the requested
        // attributes.
        final List<Entry> fullEntryList = new ArrayList<>(entryMap.size());
        findEntriesAndRefs: {
            // Check the scope.  If it is a base-level search, then we only need to
            // examine the base entry.  Otherwise, we'll have to scan the entire
            // entry map.
            final Filter filter = request.getFilter();
            if (scope == SearchScope.BASE) {
                try {
                    if (filter.matchesEntry(baseEntry, schema)) {
                        processSearchEntry(baseEntry, includeSubEntries, includeNonSubEntries, includeChangeLog, hasManageDsaIT, fullEntryList, referenceList);
                    }
                } catch (final Exception e) {
                    Debug.debugException(e);
                }
                break findEntriesAndRefs;
            }
            // set.
            if ((scope == SearchScope.ONE) && baseDN.isNullDN()) {
                for (final DN dn : baseDNs) {
                    final Entry e = entryMap.get(dn);
                    if (e != null) {
                        try {
                            if (filter.matchesEntry(e, schema)) {
                                processSearchEntry(e, includeSubEntries, includeNonSubEntries, includeChangeLog, hasManageDsaIT, fullEntryList, referenceList);
                            }
                        } catch (final Exception ex) {
                            Debug.debugException(ex);
                        }
                    }
                }
                break findEntriesAndRefs;
            }
            // Try to use indexes to process the request.  If we can't use any
            // indexes to get a candidate list, then just iterate over all the
            // entries.  It's not necessary to consider the root DSE for non-base
            // scopes.
            final Set<DN> candidateDNs = indexSearch(filter);
            if (candidateDNs == null) {
                for (final Map.Entry<DN, ReadOnlyEntry> me : entryMap.entrySet()) {
                    final DN dn = me.getKey();
                    final Entry entry = me.getValue();
                    try {
                        if (dn.matchesBaseAndScope(baseDN, scope)) {
                            if (filter.matchesEntry(entry, schema) || (((!hasManageDsaIT) && entry.hasObjectClass("referral") && entry.hasAttribute("ref")))) {
                                processSearchEntry(entry, includeSubEntries, includeNonSubEntries, includeChangeLog, hasManageDsaIT, fullEntryList, referenceList);
                            }
                        }
                    } catch (final Exception e) {
                        Debug.debugException(e);
                    }
                }
            } else {
                for (final DN dn : candidateDNs) {
                    try {
                        if (!dn.matchesBaseAndScope(baseDN, scope)) {
                            continue;
                        }
                        final Entry entry = entryMap.get(dn);
                        if (filter.matchesEntry(entry, schema) || (((!hasManageDsaIT) && entry.hasObjectClass("referral") && entry.hasAttribute("ref")))) {
                            processSearchEntry(entry, includeSubEntries, includeNonSubEntries, includeChangeLog, hasManageDsaIT, fullEntryList, referenceList);
                        }
                    } catch (final Exception e) {
                        Debug.debugException(e);
                    }
                }
            }
        }
        // If the request included the server-side sort request control, then sort
        // the matching entries appropriately.
        final ServerSideSortRequestControl sortRequestControl = (ServerSideSortRequestControl) controlMap.get(ServerSideSortRequestControl.SERVER_SIDE_SORT_REQUEST_OID);
        if (sortRequestControl != null) {
            final EntrySorter entrySorter = new EntrySorter(false, schema, sortRequestControl.getSortKeys());
            final SortedSet<Entry> sortedEntrySet = entrySorter.sort(fullEntryList);
            fullEntryList.clear();
            fullEntryList.addAll(sortedEntrySet);
            responseControls.add(new ServerSideSortResponseControl(ResultCode.SUCCESS, null));
        }
        // If the request included the simple paged results control, then handle
        // it.
        final SimplePagedResultsControl pagedResultsControl = (SimplePagedResultsControl) controlMap.get(SimplePagedResultsControl.PAGED_RESULTS_OID);
        if (pagedResultsControl != null) {
            final int totalSize = fullEntryList.size();
            final int pageSize = pagedResultsControl.getSize();
            final ASN1OctetString cookie = pagedResultsControl.getCookie();
            final int offset;
            if ((cookie == null) || (cookie.getValueLength() == 0)) {
                // This is the first request in the series, so start at the beginning
                // of the list.
                offset = 0;
            } else {
                // offset within the result list at which to start the next batch.
                try {
                    final ASN1Integer offsetInteger = ASN1Integer.decodeAsInteger(cookie.getValue());
                    offset = offsetInteger.intValue();
                } catch (final Exception e) {
                    Debug.debugException(e);
                    return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.PROTOCOL_ERROR_INT_VALUE, null, ERR_MEM_HANDLER_MALFORMED_PAGED_RESULTS_COOKIE.get(), null), responseControls);
                }
            }
            // Create an iterator that will be used to remove entries from the
            // result set that are outside of the requested page of results.
            int pos = 0;
            final Iterator<Entry> iterator = fullEntryList.iterator();
            // offset.
            while (iterator.hasNext() && (pos < offset)) {
                iterator.next();
                iterator.remove();
                pos++;
            }
            // Next, skip over the entries that should be returned.
            int keptEntries = 0;
            while (iterator.hasNext() && (keptEntries < pageSize)) {
                iterator.next();
                pos++;
                keptEntries++;
            }
            // to include in the response.  Otherwise, use an empty cookie.
            if (iterator.hasNext()) {
                responseControls.add(new SimplePagedResultsControl(totalSize, new ASN1OctetString(new ASN1Integer(pos).encode()), false));
                while (iterator.hasNext()) {
                    iterator.next();
                    iterator.remove();
                }
            } else {
                responseControls.add(new SimplePagedResultsControl(totalSize, new ASN1OctetString(), false));
            }
        }
        // If the request includes the virtual list view request control, then
        // handle it.
        final VirtualListViewRequestControl vlvRequest = (VirtualListViewRequestControl) controlMap.get(VirtualListViewRequestControl.VIRTUAL_LIST_VIEW_REQUEST_OID);
        if (vlvRequest != null) {
            final int totalEntries = fullEntryList.size();
            final ASN1OctetString assertionValue = vlvRequest.getAssertionValue();
            // Figure out the position of the target entry in the list.
            int offset = vlvRequest.getTargetOffset();
            if (assertionValue == null) {
                // The offset is one-based, so we need to adjust it for the list's
                // zero-based offset.  Also, make sure to put it within the bounds of
                // the list.
                offset--;
                offset = Math.max(0, offset);
                offset = Math.min(fullEntryList.size(), offset);
            } else {
                final SortKey primarySortKey = sortRequestControl.getSortKeys()[0];
                final Entry testEntry = new Entry("cn=test", schema, new Attribute(primarySortKey.getAttributeName(), assertionValue));
                final EntrySorter entrySorter = new EntrySorter(false, schema, primarySortKey);
                offset = fullEntryList.size();
                for (int i = 0; i < fullEntryList.size(); i++) {
                    if (entrySorter.compare(fullEntryList.get(i), testEntry) >= 0) {
                        offset = i;
                        break;
                    }
                }
            }
            // Get the start and end positions based on the before and after counts.
            final int beforeCount = Math.max(0, vlvRequest.getBeforeCount());
            final int afterCount = Math.max(0, vlvRequest.getAfterCount());
            final int start = Math.max(0, (offset - beforeCount));
            final int end = Math.min(fullEntryList.size(), (offset + afterCount + 1));
            // Create an iterator to use to alter the list so that it only contains
            // the appropriate set of entries.
            int pos = 0;
            final Iterator<Entry> iterator = fullEntryList.iterator();
            while (iterator.hasNext()) {
                iterator.next();
                if ((pos < start) || (pos >= end)) {
                    iterator.remove();
                }
                pos++;
            }
            // Create the appropriate response control.
            responseControls.add(new VirtualListViewResponseControl((offset + 1), totalEntries, ResultCode.SUCCESS, null));
        }
        // Process the set of requested attributes so that we can pare down the
        // entries.
        final SearchEntryParer parer = new SearchEntryParer(request.getAttributes(), schema);
        final int sizeLimit;
        if (request.getSizeLimit() > 0) {
            sizeLimit = Math.min(request.getSizeLimit(), maxSizeLimit);
        } else {
            sizeLimit = maxSizeLimit;
        }
        int entryCount = 0;
        for (final Entry e : fullEntryList) {
            entryCount++;
            if (entryCount > sizeLimit) {
                return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.SIZE_LIMIT_EXCEEDED_INT_VALUE, null, ERR_MEM_HANDLER_SEARCH_SIZE_LIMIT_EXCEEDED.get(), null), responseControls);
            }
            final Entry trimmedEntry = parer.pareEntry(e);
            if (request.typesOnly()) {
                final Entry typesOnlyEntry = new Entry(trimmedEntry.getDN(), schema);
                for (final Attribute a : trimmedEntry.getAttributes()) {
                    typesOnlyEntry.addAttribute(new Attribute(a.getName()));
                }
                entryList.add(new SearchResultEntry(typesOnlyEntry));
            } else {
                entryList.add(new SearchResultEntry(trimmedEntry));
            }
        }
        return new LDAPMessage(messageID, new SearchResultDoneProtocolOp(ResultCode.SUCCESS_INT_VALUE, null, null, null), responseControls);
    }
}
Also used : ASN1OctetString(com.unboundid.asn1.ASN1OctetString) Attribute(com.unboundid.ldap.sdk.Attribute) Schema(com.unboundid.ldap.sdk.schema.Schema) ArrayList(java.util.ArrayList) RDN(com.unboundid.ldap.sdk.RDN) DN(com.unboundid.ldap.sdk.DN) SortKey(com.unboundid.ldap.sdk.controls.SortKey) ASN1OctetString(com.unboundid.asn1.ASN1OctetString) VirtualListViewRequestControl(com.unboundid.ldap.sdk.controls.VirtualListViewRequestControl) SubtreeDeleteRequestControl(com.unboundid.ldap.sdk.controls.SubtreeDeleteRequestControl) RFC3672SubentriesRequestControl(com.unboundid.ldap.sdk.controls.RFC3672SubentriesRequestControl) SimplePagedResultsControl(com.unboundid.ldap.sdk.controls.SimplePagedResultsControl) VirtualListViewResponseControl(com.unboundid.ldap.sdk.controls.VirtualListViewResponseControl) TransactionSpecificationRequestControl(com.unboundid.ldap.sdk.controls.TransactionSpecificationRequestControl) DraftZeilengaLDAPNoOp12RequestControl(com.unboundid.ldap.sdk.experimental.DraftZeilengaLDAPNoOp12RequestControl) PostReadRequestControl(com.unboundid.ldap.sdk.controls.PostReadRequestControl) ProxiedAuthorizationV1RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV1RequestControl) ServerSideSortResponseControl(com.unboundid.ldap.sdk.controls.ServerSideSortResponseControl) PreReadResponseControl(com.unboundid.ldap.sdk.controls.PreReadResponseControl) AuthorizationIdentityResponseControl(com.unboundid.ldap.sdk.controls.AuthorizationIdentityResponseControl) PermissiveModifyRequestControl(com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl) AuthorizationIdentityRequestControl(com.unboundid.ldap.sdk.controls.AuthorizationIdentityRequestControl) Control(com.unboundid.ldap.sdk.Control) IgnoreNoUserModificationRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.IgnoreNoUserModificationRequestControl) ProxiedAuthorizationV2RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl) ServerSideSortRequestControl(com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl) PostReadResponseControl(com.unboundid.ldap.sdk.controls.PostReadResponseControl) DontUseCopyRequestControl(com.unboundid.ldap.sdk.controls.DontUseCopyRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl) DraftLDUPSubentriesRequestControl(com.unboundid.ldap.sdk.controls.DraftLDUPSubentriesRequestControl) PreReadRequestControl(com.unboundid.ldap.sdk.controls.PreReadRequestControl) ChangeLogEntry(com.unboundid.ldap.sdk.ChangeLogEntry) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) Entry(com.unboundid.ldap.sdk.Entry) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) SearchResultDoneProtocolOp(com.unboundid.ldap.protocol.SearchResultDoneProtocolOp) ServerSideSortResponseControl(com.unboundid.ldap.sdk.controls.ServerSideSortResponseControl) LDAPMessage(com.unboundid.ldap.protocol.LDAPMessage) ASN1Integer(com.unboundid.asn1.ASN1Integer) LDAPException(com.unboundid.ldap.sdk.LDAPException) LDIFException(com.unboundid.ldif.LDIFException) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) ServerSideSortRequestControl(com.unboundid.ldap.sdk.controls.ServerSideSortRequestControl) VirtualListViewResponseControl(com.unboundid.ldap.sdk.controls.VirtualListViewResponseControl) LDAPException(com.unboundid.ldap.sdk.LDAPException) RFC3672SubentriesRequestControl(com.unboundid.ldap.sdk.controls.RFC3672SubentriesRequestControl) Filter(com.unboundid.ldap.sdk.Filter) VirtualListViewRequestControl(com.unboundid.ldap.sdk.controls.VirtualListViewRequestControl) SearchScope(com.unboundid.ldap.sdk.SearchScope) SimplePagedResultsControl(com.unboundid.ldap.sdk.controls.SimplePagedResultsControl) EntrySorter(com.unboundid.ldap.sdk.EntrySorter) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap) HashMap(java.util.HashMap) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) NotNull(com.unboundid.util.NotNull)

Example 4 with ReadOnlyEntry

use of com.unboundid.ldap.sdk.ReadOnlyEntry in project ldapsdk by pingidentity.

the class InMemoryRequestHandler method search.

/**
 * Retrieves a list of all entries in the server which match the given
 * search criteria.
 *
 * @param  baseDN  The base DN to use for the search.  It must not be
 *                 {@code null}.
 * @param  scope   The scope to use for the search.  It must not be
 *                 {@code null}.
 * @param  filter  The filter to use for the search.  It must not be
 *                 {@code null}.
 *
 * @return  A list of the entries that matched the provided search criteria.
 *
 * @throws  LDAPException  If a problem is encountered while performing the
 *                         search.
 */
@NotNull()
public List<ReadOnlyEntry> search(@NotNull final String baseDN, @NotNull final SearchScope scope, @NotNull final Filter filter) throws LDAPException {
    synchronized (entryMap) {
        final DN parsedDN;
        final Schema schema = schemaRef.get();
        try {
            parsedDN = new DN(baseDN, schema);
        } catch (final LDAPException le) {
            Debug.debugException(le);
            throw new LDAPException(ResultCode.INVALID_DN_SYNTAX, ERR_MEM_HANDLER_SEARCH_MALFORMED_BASE.get(baseDN, le.getMessage()), le);
        }
        final ReadOnlyEntry baseEntry;
        if (parsedDN.isNullDN()) {
            baseEntry = generateRootDSE();
        } else if (parsedDN.equals(subschemaSubentryDN)) {
            baseEntry = subschemaSubentryRef.get();
        } else {
            final Entry e = entryMap.get(parsedDN);
            if (e == null) {
                throw new LDAPException(ResultCode.NO_SUCH_OBJECT, ERR_MEM_HANDLER_SEARCH_BASE_DOES_NOT_EXIST.get(baseDN), getMatchedDNString(parsedDN), null);
            }
            baseEntry = new ReadOnlyEntry(e);
        }
        if (scope == SearchScope.BASE) {
            final List<ReadOnlyEntry> entryList = new ArrayList<>(1);
            try {
                if (filter.matchesEntry(baseEntry, schema)) {
                    entryList.add(baseEntry);
                }
            } catch (final LDAPException le) {
                Debug.debugException(le);
            }
            return Collections.unmodifiableList(entryList);
        }
        if ((scope == SearchScope.ONE) && parsedDN.isNullDN()) {
            final List<ReadOnlyEntry> entryList = new ArrayList<>(baseDNs.size());
            try {
                for (final DN dn : baseDNs) {
                    final Entry e = entryMap.get(dn);
                    if ((e != null) && filter.matchesEntry(e, schema)) {
                        entryList.add(new ReadOnlyEntry(e));
                    }
                }
            } catch (final LDAPException le) {
                Debug.debugException(le);
            }
            return Collections.unmodifiableList(entryList);
        }
        final List<ReadOnlyEntry> entryList = new ArrayList<>(10);
        for (final Map.Entry<DN, ReadOnlyEntry> me : entryMap.entrySet()) {
            final DN dn = me.getKey();
            if (dn.matchesBaseAndScope(parsedDN, scope)) {
                // root DSE.
                if (parsedDN.isNullDN() && dn.isDescendantOf(changeLogBaseDN, true)) {
                    continue;
                }
                try {
                    final Entry entry = me.getValue();
                    if (filter.matchesEntry(entry, schema)) {
                        entryList.add(new ReadOnlyEntry(entry));
                    }
                } catch (final LDAPException le) {
                    Debug.debugException(le);
                }
            }
        }
        return Collections.unmodifiableList(entryList);
    }
}
Also used : ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) ChangeLogEntry(com.unboundid.ldap.sdk.ChangeLogEntry) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) Entry(com.unboundid.ldap.sdk.Entry) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) LDAPException(com.unboundid.ldap.sdk.LDAPException) Schema(com.unboundid.ldap.sdk.schema.Schema) ArrayList(java.util.ArrayList) RDN(com.unboundid.ldap.sdk.RDN) DN(com.unboundid.ldap.sdk.DN) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap) HashMap(java.util.HashMap) NotNull(com.unboundid.util.NotNull)

Example 5 with ReadOnlyEntry

use of com.unboundid.ldap.sdk.ReadOnlyEntry in project ldapsdk by pingidentity.

the class InMemoryRequestHandler method generateSubschemaSubentry.

/**
 * Generates a subschema subentry from the provided schema object.
 *
 * @param  schema  The schema to use to generate the subschema subentry.  It
 *                 may be {@code null} if a minimal default entry should be
 *                 generated.
 *
 * @return  The generated subschema subentry.
 */
@NotNull()
private static ReadOnlyEntry generateSubschemaSubentry(@Nullable final Schema schema) {
    final Entry e;
    if (schema == null) {
        e = new Entry("cn=schema", schema);
        e.addAttribute("objectClass", "namedObject", "ldapSubEntry", "subschema");
        e.addAttribute("cn", "schema");
    } else {
        e = schema.getSchemaEntry().duplicate();
    }
    try {
        e.addAttribute("entryDN", DN.normalize(e.getDN(), schema));
    } catch (final LDAPException le) {
        // This should never happen.
        Debug.debugException(le);
        e.setAttribute("entryDN", StaticUtils.toLowerCase(e.getDN()));
    }
    e.addAttribute("entryUUID", CryptoHelper.getRandomUUID().toString());
    return new ReadOnlyEntry(e);
}
Also used : ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) ChangeLogEntry(com.unboundid.ldap.sdk.ChangeLogEntry) SearchResultEntry(com.unboundid.ldap.sdk.SearchResultEntry) Entry(com.unboundid.ldap.sdk.Entry) ReadOnlyEntry(com.unboundid.ldap.sdk.ReadOnlyEntry) LDAPException(com.unboundid.ldap.sdk.LDAPException) NotNull(com.unboundid.util.NotNull)

Aggregations

ReadOnlyEntry (com.unboundid.ldap.sdk.ReadOnlyEntry)94 Test (org.testng.annotations.Test)64 ASN1OctetString (com.unboundid.asn1.ASN1OctetString)41 Entry (com.unboundid.ldap.sdk.Entry)29 DN (com.unboundid.ldap.sdk.DN)27 Attribute (com.unboundid.ldap.sdk.Attribute)25 Modification (com.unboundid.ldap.sdk.Modification)21 LDAPException (com.unboundid.ldap.sdk.LDAPException)18 ChangeLogEntry (com.unboundid.ldap.sdk.ChangeLogEntry)16 Control (com.unboundid.ldap.sdk.Control)14 SearchResultEntry (com.unboundid.ldap.sdk.SearchResultEntry)14 NotNull (com.unboundid.util.NotNull)14 RDN (com.unboundid.ldap.sdk.RDN)12 ArrayList (java.util.ArrayList)12 LDAPResult (com.unboundid.ldap.sdk.LDAPResult)9 PostReadResponseControl (com.unboundid.ldap.sdk.controls.PostReadResponseControl)8 PreReadResponseControl (com.unboundid.ldap.sdk.controls.PreReadResponseControl)8 Schema (com.unboundid.ldap.sdk.schema.Schema)8 AuthorizationIdentityResponseControl (com.unboundid.ldap.sdk.controls.AuthorizationIdentityResponseControl)7 ServerSideSortResponseControl (com.unboundid.ldap.sdk.controls.ServerSideSortResponseControl)7