package org.ovirt.engine.core.bll.adbroker; import java.net.URI; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.compat.LogCompat; import org.ovirt.engine.core.compat.LogFactoryCompat; import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil; public class DirectorySearcher { private static final Object DC_PREFIX = "DC="; private boolean baseDNExist = true; private boolean explicitAuth = false; private String explicitBaseDN; private static final LogCompat log = LogFactoryCompat.getLog(DirectorySearcher.class); private final LdapCredentials ldapCredentials; private Exception ex; private static final ExceptionHandler<LdapSearchExceptionHandlingResponse> handler = new LdapSearchExceptionHandler(); public void setExplicitAuth(boolean explicitAuth) { this.explicitAuth = explicitAuth; } public boolean getExplicitAuth() { return explicitAuth; } public DirectorySearcher(LdapCredentials ldapCredentials) { this.ldapCredentials = ldapCredentials; } public Object FindOne(LdapQueryData ldapQueryData) { List<Object> userObjects = find(ldapQueryData, 1); if (userObjects == null || userObjects.size() == 0) { return null; } return userObjects.get(0); } public List FindAll(LdapQueryData ldapQueryData) { List returnValue = find(ldapQueryData, 0); if (returnValue == null) { returnValue = Collections.EMPTY_LIST; } return returnValue; } protected GetRootDSE createRootDSE(URI uri) { return new GetRootDSE(uri); } protected Domain getDomainObject(String domainName) { Domain domainObject = UsersDomainsCacheManagerService.getInstance().getDomain(domainName); return domainObject; } public List find(final LdapQueryData queryData, final long resultCount) { final String domainName = queryData.getDomain(); final Domain domain = getDomainObject(domainName); if (domain == null) { log.errorFormat("Error in finding LDAP servers for domain {0}", domainName); return null; } List<URI> ldapServerURIs = domain.getLdapServers(); if (log.isDebugEnabled()) { log.debug("Ldap server list ordered by highest score: " + StringUtils.join(ldapServerURIs, ", ")); } List response = null; for (Iterator<URI> iterator = ldapServerURIs.iterator(); iterator.hasNext();) { URI ldapURI = iterator.next(); if (log.isDebugEnabled()) { log.debug("Using Ldap server " + ldapURI); } try { setException(null); final GetRootDSETask getRootDSETask = new GetRootDSETask(this, domainName, ldapURI); final PrepareLdapConnectionTask prepareLdapConnectionTask = new PrepareLdapConnectionTask(this, ldapCredentials, domainName, ldapURI); FutureTask<List> searchTask = new FutureTask<List>(new Callable<List>() { @Override public List call() throws Exception { getRootDSETask.call(); final LdapQueryExecution queryExecution = LdapQueryExecutionBuilderImpl.getInstance() .build(getDomainObject(domainName).getLdapProviderType(), queryData); if (queryExecution.getBaseDN() != null && !queryExecution.getBaseDN().isEmpty()) { setExplicitBaseDN(queryExecution.getBaseDN()); } LDAPTemplateWrapper ldapTemplate = prepareLdapConnectionTask.call(); if (ldapTemplate == null) { return Collections.emptyList(); } return new DirectorySearchTask(ldapTemplate, queryExecution, resultCount).call(); } }); ThreadPoolUtil.execute(searchTask); response = searchTask.get(Config.<Integer> GetValue(ConfigValues.LDAPQueryTimeout), TimeUnit.SECONDS); domain.scoreLdapServer(ldapURI, Score.HIGH); return response; // No point in continuing to next LDAP server if we have success. } catch (Exception exception) { LdapSearchExceptionHandlingResponse handlingResponse = handler.handle(exception); setException(handlingResponse.getTranslatedException()); domain.scoreLdapServer(ldapURI, handlingResponse.getServerScore()); log.errorFormat("Failed ldap search server {0} due to {1}. We {2} try the next server", ldapURI, handlingResponse.getTranslatedException(), handlingResponse.isTryNextServer() ? "should" : "should not"); if (!handlingResponse.isTryNextServer()) { return Collections.emptyList(); } } } return response; } public void setException(Exception ex) { this.ex = ex; } public Exception getException() { return ex; } protected String getBaseDNForDomainForSimpleAuth(String domainName) { if (domainName == null) { return null; } StringBuilder dnSb = new StringBuilder(); String[] parts = domainName.split("\\."); // format should be dc=part0,dc=part1,dc=part2,.....dc=part-(n-1) for (int counter = 0; counter < parts.length; counter++) { dnSb.append(DC_PREFIX).append(parts[counter]); if (counter < parts.length - 1) { dnSb.append(","); } } return dnSb.toString(); } public void setExplicitBaseDN(String explicitBaseDN) { this.explicitBaseDN = explicitBaseDN; } public String getExplicitBaseDN() { return explicitBaseDN; } public boolean isBaseDNExist() { return baseDNExist; } public void setBaseDNExist(boolean baseDNExist) { this.baseDNExist = baseDNExist; } }