Skip to content

Commit

Permalink
[LDAP-45] Search strategy internal search fixes (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sylinsic authored Feb 29, 2024
1 parent 9dc6036 commit 903cdf4
Show file tree
Hide file tree
Showing 18 changed files with 383 additions and 789 deletions.
39 changes: 26 additions & 13 deletions src/main/java/net/tirasa/connid/bundles/ldap/LdapConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ public enum SearchScope {

private String changeLogContext = "cn=changelog";

private boolean changeLogPagingSupport = false;

private boolean filterWithOrInsteadOfAnd;

private boolean removeLogEntryObjectClassFromFilter = true;
Expand Down Expand Up @@ -903,7 +905,18 @@ public void setChangeLogContext(String changeLogContext) {
this.changeLogContext = changeLogContext;
}

@ConfigurationProperty(order = 39, operations = { SyncOp.class },
@ConfigurationProperty(order = 40, operations = { SyncOp.class },
displayMessageKey = "changeLogPagingSupport.display",
helpMessageKey = "changeLogPagingSupport.help")
public boolean getChangeLogPagingSupport() {
return changeLogPagingSupport;
}

public void setChangeLogPagingSupport(boolean changeLogPagingSupport) {
this.changeLogPagingSupport = changeLogPagingSupport;
}

@ConfigurationProperty(order = 41, operations = { SyncOp.class },
displayMessageKey = "filterWithOrInsteadOfAnd.display",
helpMessageKey = "filterWithOrInsteadOfAnd.help")
public boolean isFilterWithOrInsteadOfAnd() {
Expand All @@ -914,7 +927,7 @@ public void setFilterWithOrInsteadOfAnd(boolean filterWithOrInsteadOfAnd) {
this.filterWithOrInsteadOfAnd = filterWithOrInsteadOfAnd;
}

@ConfigurationProperty(order = 40, operations = { SyncOp.class },
@ConfigurationProperty(order = 42, operations = { SyncOp.class },
displayMessageKey = "removeLogEntryObjectClassFromFilter.display",
helpMessageKey = "removeLogEntryObjectClassFromFilter.help")
public boolean isRemoveLogEntryObjectClassFromFilter() {
Expand All @@ -925,7 +938,7 @@ public void setRemoveLogEntryObjectClassFromFilter(boolean removeLogEntryObjectC
this.removeLogEntryObjectClassFromFilter = removeLogEntryObjectClassFromFilter;
}

@ConfigurationProperty(order = 41, operations = { SyncOp.class },
@ConfigurationProperty(order = 43, operations = { SyncOp.class },
displayMessageKey = "synchronizePasswords.display",
helpMessageKey = "synchronizePasswords.help")
public boolean isSynchronizePasswords() {
Expand All @@ -936,7 +949,7 @@ public void setSynchronizePasswords(boolean synchronizePasswords) {
this.synchronizePasswords = synchronizePasswords;
}

@ConfigurationProperty(order = 42, operations = { SyncOp.class },
@ConfigurationProperty(order = 44, operations = { SyncOp.class },
displayMessageKey = "passwordAttributeToSynchronize.display",
helpMessageKey = "passwordAttributeToSynchronize.help")
public String getPasswordAttributeToSynchronize() {
Expand All @@ -947,7 +960,7 @@ public void setPasswordAttributeToSynchronize(String passwordAttributeToSynchron
this.passwordAttributeToSynchronize = passwordAttributeToSynchronize;
}

@ConfigurationProperty(order = 43, operations = { SyncOp.class }, confidential = true,
@ConfigurationProperty(order = 45, operations = { SyncOp.class }, confidential = true,
displayMessageKey = "passwordDecryptionKey.display",
helpMessageKey = "passwordDecryptionKey.help")
public GuardedByteArray getPasswordDecryptionKey() {
Expand All @@ -959,7 +972,7 @@ public void setPasswordDecryptionKey(GuardedByteArray passwordDecryptionKey) {
copy() : null;
}

@ConfigurationProperty(order = 44, operations = { SyncOp.class }, confidential = true,
@ConfigurationProperty(order = 46, operations = { SyncOp.class }, confidential = true,
displayMessageKey = "passwordDecryptionInitializationVector.display",
helpMessageKey = "passwordDecryptionInitializationVector.help")
public GuardedByteArray getPasswordDecryptionInitializationVector() {
Expand All @@ -971,7 +984,7 @@ public void setPasswordDecryptionInitializationVector(GuardedByteArray passwordD
? passwordDecryptionInitializationVector.copy() : null;
}

@ConfigurationProperty(order = 45,
@ConfigurationProperty(order = 47,
displayMessageKey = "statusManagementClass.display",
helpMessageKey = "statusManagementClass.help")
public String getStatusManagementClass() {
Expand All @@ -982,7 +995,7 @@ public void setStatusManagementClass(String statusManagementClass) {
this.statusManagementClass = statusManagementClass;
}

@ConfigurationProperty(order = 46,
@ConfigurationProperty(order = 48,
displayMessageKey = "retrievePasswordsWithSearch.display",
helpMessageKey = "retrievePasswordsWithSearch.help")
public boolean getRetrievePasswordsWithSearch() {
Expand All @@ -993,7 +1006,7 @@ public void setRetrievePasswordsWithSearch(boolean retrievePasswordsWithSearch)
this.retrievePasswordsWithSearch = retrievePasswordsWithSearch;
}

@ConfigurationProperty(order = 47,
@ConfigurationProperty(order = 49,
displayMessageKey = "dnAttribute.display",
helpMessageKey = "dnAttribute.help")
public String getDnAttribute() {
Expand All @@ -1004,7 +1017,7 @@ public void setDnAttribute(String dnAttribute) {
this.dnAttribute = dnAttribute;
}

@ConfigurationProperty(order = 48,
@ConfigurationProperty(order = 50,
displayMessageKey = "groupSearchFilter.display",
helpMessageKey = "groupSearchFilter.help")
public String getGroupSearchFilter() {
Expand All @@ -1015,7 +1028,7 @@ public void setGroupSearchFilter(String groupSearchFilter) {
this.groupSearchFilter = groupSearchFilter;
}

@ConfigurationProperty(order = 49,
@ConfigurationProperty(order = 51,
displayMessageKey = "readTimeout.display",
helpMessageKey = "readTimeout.help")
public long getReadTimeout() {
Expand All @@ -1026,7 +1039,7 @@ public void setReadTimeout(long readTimeout) {
this.readTimeout = readTimeout;
}

@ConfigurationProperty(order = 50,
@ConfigurationProperty(order = 52,
displayMessageKey = "connectTimeout.display",
helpMessageKey = "connectTimeout.help")
public long getConnectTimeout() {
Expand All @@ -1037,7 +1050,7 @@ public void setConnectTimeout(long connectTimeout) {
this.connectTimeout = connectTimeout;
}

@ConfigurationProperty(order = 51,
@ConfigurationProperty(order = 53,
displayMessageKey = "syncStrategy.display",
helpMessageKey = "syncStrategy.help")
public String getSyncStrategy() {
Expand Down
24 changes: 16 additions & 8 deletions src/main/java/net/tirasa/connid/bundles/ldap/commons/LdapUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ private LdapUtil() {
}

/**
* Returns true if the names of the given LDAP attributes are equal. Deals
* with null values as a convenience.
* @return @code true} if the names of the given LDAP attributes are equal. Deals with null values as a convenience.
*/
public static boolean attrNameEquals(String name1, String name2) {
if (name1 == null) {
Expand All @@ -61,8 +60,7 @@ public static boolean attrNameEquals(String name1, String name2) {
}

/**
* Returns {@code true} if the attribute has the binary option,
* e.g., {@code userCertificate;binary}.
* @return {@code true} if the attribute has the binary option, e.g., {@code userCertificate;binary}.
*/
public static boolean hasBinaryOption(String ldapAttrName) {
return ldapAttrName.toLowerCase(Locale.US).endsWith(LDAP_BINARY_OPTION);
Expand All @@ -89,7 +87,7 @@ public static String removeBinaryOption(String ldapAttrName) {
}

/**
* Return the value of the {@code ldapAttrName} parameter cast to a String.
* @return the value of the {@code ldapAttrName} parameter cast to a String.
*/
public static String getStringAttrValue(Attributes ldapAttrs, String ldapAttrName) {
Attribute attr = ldapAttrs.get(ldapAttrName);
Expand All @@ -104,11 +102,11 @@ public static String getStringAttrValue(Attributes ldapAttrs, String ldapAttrNam
}

/**
* Return the <b>case insensitive</b> set of values of the {@code
* @return the <b>case insensitive</b> set of values of the {@code
* ldapAttrName} parameter cast to a String.
*/
public static Set<String> getStringAttrValues(Attributes ldapAttrs, String ldapAttrName) {
Set<String> result = new HashSet<String>();
Set<String> result = new HashSet<>();
addStringAttrValues(ldapAttrs, ldapAttrName, result);
return result;
}
Expand All @@ -130,7 +128,8 @@ public static void addStringAttrValues(Attributes ldapAttrs, String ldapAttrName

/**
* Escapes the given attribute value to the given {@code StringBuilder}.
* Returns {@code true} iff anything was written to the builder.
*
* @returns {@code true} iff anything was written to the builder.
*/
public static boolean escapeAttrValue(Object value, StringBuilder toBuilder) {
if (value == null) {
Expand Down Expand Up @@ -431,38 +430,47 @@ public ListItr(ListIterator iter) {
this.iter = iter;
}

@Override
public void add(E o) {
iter.add(o);
}

@Override
public boolean hasNext() {
return iter.hasNext();
}

@Override
public boolean hasPrevious() {
return iter.hasPrevious();
}

@Override
public E next() {
return cast(iter.next());
}

@Override
public int nextIndex() {
return iter.nextIndex();
}

@Override
public E previous() {
return cast(iter.previous());
}

@Override
public int previousIndex() {
return iter.previousIndex();
}

@Override
public void remove() {
iter.remove();
}

@Override
public void set(E o) {
iter.set(o);
}
Expand Down
37 changes: 26 additions & 11 deletions src/main/java/net/tirasa/connid/bundles/ldap/search/LdapSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public class LdapSearch {
// An Operation Option specific for usage with LDAP
public static final String OP_IGNORE_CUSTOM_ANY_OBJECT_CONFIG = "IGNORE_CUSTOM_ANY_OBJECT_CONFIG";

public static final String OP_IGNORE_BUILT_IN_FILTERS = "IGNORE_BUILT_IN_FILTERS";

private static final Log LOG = Log.getLog(LdapSearch.class);

protected final LdapConnection conn;
Expand Down Expand Up @@ -208,18 +210,31 @@ protected LdapInternalSearch getInternalSearch(final Set<String> attrsToGet) {
controls.setSearchScope(searchScope);

String optionsFilter = LdapConstants.getSearchFilter(options);
String searchFilter = null;
if (oclass.equals(ObjectClass.ACCOUNT)) {
searchFilter = conn.getConfiguration().getAccountSearchFilter();
} else if (oclass.equals(ObjectClass.GROUP)) {
searchFilter = conn.getConfiguration().getGroupSearchFilter();
} else if (!ignoreUserAnyObjectConfig) {
searchFilter = conn.getConfiguration().getAnyObjectSearchFilter();

boolean ignoreBuiltInFilters;
if (options.getOptions().containsKey(OP_IGNORE_BUILT_IN_FILTERS)) {
ignoreBuiltInFilters = (boolean) options.getOptions().get(OP_IGNORE_BUILT_IN_FILTERS);
} else {
ignoreBuiltInFilters = false;
}

String finalFilter;
if (ignoreBuiltInFilters) {
finalFilter = optionsFilter;
} else {
String searchFilter = null;
if (oclass.equals(ObjectClass.ACCOUNT)) {
searchFilter = conn.getConfiguration().getAccountSearchFilter();
} else if (oclass.equals(ObjectClass.GROUP)) {
searchFilter = conn.getConfiguration().getGroupSearchFilter();
} else if (!ignoreUserAnyObjectConfig) {
searchFilter = conn.getConfiguration().getAnyObjectSearchFilter();
}
String nativeFilter = filter == null ? null : filter.getNativeFilter();

finalFilter = getSearchFilter(optionsFilter, nativeFilter, searchFilter);
}
String nativeFilter = filter == null ? null : filter.getNativeFilter();
return new LdapInternalSearch(conn,
getSearchFilter(optionsFilter, nativeFilter, searchFilter),
dns, strategy, controls);
return new LdapInternalSearch(conn, finalFilter, dns, strategy, controls);
}

protected Set<String> getLdapAttributesToGet(final Set<String> attrsToGet) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/*
/*
* ====================
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
*
* Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.
*
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License("CDDL") (the "License"). You may not use this file
* except in compliance with the License.
*
*
* You can obtain a copy of the License at
* http://opensource.org/licenses/cddl1.php
* See the License for the specific language governing permissions and limitations
* under the License.
*
*
* When distributing the Covered Code, include this CDDL Header Notice in each file
* and include the License file at http://opensource.org/licenses/cddl1.php.
* If applicable, add the following below this CDDL Header, with the fields
Expand All @@ -29,6 +29,12 @@
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.PagedResultsControl;
import com.sun.jndi.ldap.ctl.VirtualListViewControl;

import org.identityconnectors.framework.common.objects.OperationOptions;

import net.tirasa.connid.bundles.ldap.LdapConnection;

public abstract class LdapSearchStrategy {

Expand Down Expand Up @@ -66,4 +72,17 @@ protected static String searchControlsToString(final SearchControls controls) {
builder.append('}');
return builder.toString();
}

public static Class<? extends LdapSearchStrategy> getSearchStrategy(LdapConnection conn, OperationOptions options) {
Class<? extends LdapSearchStrategy> clazz = DefaultSearchStrategy.class;
if (options.getPageSize() != null) {
if (conn.getConfiguration().isUseVlvControls() && conn.supportsControl(VirtualListViewControl.OID)) {
clazz = VlvIndexSearchStrategy.class;
} else if (conn.supportsControl(PagedResultsControl.OID)) {
clazz = PagedSearchStrategy.class;
}
}

return clazz;
}
}
Loading

0 comments on commit 903cdf4

Please sign in to comment.