Example usage for javax.naming.directory SearchControls setReturningAttributes

List of usage examples for javax.naming.directory SearchControls setReturningAttributes

Introduction

In this page you can find the example usage for javax.naming.directory SearchControls setReturningAttributes.

Prototype

public void setReturningAttributes(String[] attrs) 

Source Link

Document

Specifies the attributes that will be returned as part of the search.

Usage

From source file:org.lsc.jndi.FullDNJndiDstService.java

/**
 * The simple object getter according to its identifier.
 * //from   www. j a va 2s . co  m
 * @param dn DN of the entry to be returned, which is the name returned by {@link #getListPivots()}
 * @param pivotAttributes Unused.
 * @param fromSameService are the pivot attributes provided by the same service
 * @return The bean, or null if not found
 * @throws LscServiceException May throw a {@link NamingException} if the object is not found in the
 *             directory, or if more than one object would be returned. 
 */
public IBean getBean(String dn, LscDatasets pivotAttributes, boolean fromSameService)
        throws LscServiceException {

    try {
        SearchControls sc = new SearchControls();
        sc.setSearchScope(SearchControls.OBJECT_SCOPE);
        List<String> attrs = getAttrs();
        if (attrs != null) {
            sc.setReturningAttributes(attrs.toArray(new String[attrs.size()]));
        }
        SearchResult srObject = getJndiServices().readEntry(dn, getFilterId(), true, sc);
        Method method = beanClass.getMethod("getInstance",
                new Class[] { SearchResult.class, String.class, Class.class });
        return (IBean) method.invoke(null, new Object[] { srObject, jndiServices.completeDn(dn), beanClass });

    } catch (SecurityException e) {
        LOGGER.error(
                "Unable to get static method getInstance on {} ! This is probably a programmer's error ({})",
                beanClass.getName(), e);
        LOGGER.debug(e.toString(), e);
    } catch (NoSuchMethodException e) {
        LOGGER.error(
                "Unable to get static method getInstance on {} ! This is probably a programmer's error ({})",
                beanClass.getName(), e);
        LOGGER.debug(e.toString(), e);
    } catch (IllegalArgumentException e) {
        LOGGER.error(
                "Unable to get static method getInstance on {} ! This is probably a programmer's error ({})",
                beanClass.getName(), e);
        LOGGER.debug(e.toString(), e);
    } catch (IllegalAccessException e) {
        LOGGER.error(
                "Unable to get static method getInstance on {} ! This is probably a programmer's error ({})",
                beanClass.getName(), e);
        LOGGER.debug(e.toString(), e);
    } catch (InvocationTargetException e) {
        LOGGER.error(
                "Unable to get static method getInstance on {} ! This is probably a programmer's error ({})",
                beanClass.getName(), e);
        LOGGER.debug(e.toString(), e);
    } catch (NamingException e) {
        LOGGER.error("JNDI error while synchronizing {}: {} ", beanClass.getName(), e);
        LOGGER.debug(e.toString(), e);
        throw new LscServiceException(e.toString(), e);
    }
    return null;
}

From source file:org.lsc.jndi.JndiServices.java

private List<String> doGetDnList(final String base, final String filter, final int scope)
        throws NamingException {
    NamingEnumeration<SearchResult> ne = null;
    List<String> iist = new ArrayList<String>();
    try {//from w w  w.ja v a2 s . c  o m
        SearchControls sc = new SearchControls();
        sc.setDerefLinkFlag(false);
        sc.setReturningAttributes(new String[] { "1.1" });
        sc.setSearchScope(scope);
        sc.setReturningObjFlag(true);
        ne = ctx.search(base, filter, sc);

        String completedBaseDn = "";
        if (base.length() > 0) {
            completedBaseDn = "," + base;
        }
        while (ne.hasMoreElements()) {
            iist.add(((SearchResult) ne.next()).getName() + completedBaseDn);
        }
    } catch (NamingException e) {
        LOGGER.error(e.toString());
        LOGGER.debug(e.toString(), e);
        throw e;
    }
    return iist;
}

From source file:org.lsc.jndi.JndiServices.java

/**
 * Return the LDAP schema./*from  ww  w .  j  a v a  2  s. c  o m*/
 *
 * @param attrsToReturn
 *                list of attribute names to return (or null for all
 *                'standard' attributes)
 * @return the map of name => attribute
 * @throws NamingException
 *                 thrown if something goes wrong (bad
 */
@SuppressWarnings("unchecked")
public Map<String, List<String>> getSchema(final String[] attrsToReturn) throws NamingException {
    Map<String, List<String>> attrsResult = new HashMap<String, List<String>>();

    // connect to directory
    Hashtable<String, String> props = (Hashtable<String, String>) ctx.getEnvironment();
    String baseUrl = (String) props.get(Context.PROVIDER_URL);
    baseUrl = baseUrl.substring(0, baseUrl.lastIndexOf('/'));
    props.put(Context.PROVIDER_URL, baseUrl);
    DirContext schemaCtx = new InitialLdapContext(props, null);

    // find schema entry
    SearchControls sc = new SearchControls();
    sc.setSearchScope(SearchControls.OBJECT_SCOPE);
    sc.setReturningAttributes(new String[] { "subschemaSubentry" });

    NamingEnumeration<SearchResult> schemaDnSR = schemaCtx.search("", "(objectclass=*)", sc);

    SearchResult sr = null;
    Attribute subschemaSubentry = null;
    String subschemaSubentryDN = null;

    if (schemaDnSR.hasMore()) {
        sr = schemaDnSR.next();
    }
    if (sr != null) {
        subschemaSubentry = sr.getAttributes().get("subschemaSubentry");
    }
    if (subschemaSubentry != null && subschemaSubentry.size() > 0) {
        subschemaSubentryDN = (String) subschemaSubentry.get();
    }

    if (subschemaSubentryDN != null) {
        // get schema attributes from subschemaSubentryDN
        Attributes schemaAttrs = schemaCtx.getAttributes(subschemaSubentryDN,
                attrsToReturn != null ? attrsToReturn : new String[] { "*", "+" });

        if (schemaAttrs != null) {
            for (String attr : attrsToReturn) {
                Attribute schemaAttr = schemaAttrs.get(attr);
                if (schemaAttr != null) {
                    attrsResult.put(schemaAttr.getID(), (List<String>) Collections.list(schemaAttr.getAll()));
                }
            }
        }
    }

    return attrsResult;
}

From source file:org.lsc.jndi.JndiServices.java

/**
 * Retrieve a specific attribute from an object
 * //ww  w. jav  a  2s . com
 * @param objectDn
 * @param attribute
 * @return
 * @throws LscServiceException
 */
public List<String> getAttributeValues(String objectDn, String attribute) throws LscServiceException {
    List<String> values = null;
    try {
        // Setup search
        SearchControls sc = new SearchControls();
        sc.setDerefLinkFlag(false);
        sc.setReturningAttributes(new String[] { attribute });
        sc.setSearchScope(SearchControls.OBJECT_SCOPE);
        sc.setReturningObjFlag(true);

        // Retrieve attribute values
        SearchResult res = getEntry(objectDn, "objectClass=*", sc, SearchControls.OBJECT_SCOPE);
        Attribute attr = res.getAttributes().get(attribute);
        if (attr != null) {
            values = new ArrayList<String>();
            NamingEnumeration<?> enu = attr.getAll();
            while (enu.hasMoreElements()) {
                Object val = enu.next();
                values.add(val.toString());
            }
        }
    } catch (NamingException e) {
        throw new LscServiceException(e);
    }
    return values;
}

From source file:org.lsc.jndi.JndiServices.java

public Map<String, LscDatasets> doGetAttrsList(final String base, final String filter, final int scope,
        final List<String> attrsNames) throws NamingException {

    // sanity checks
    String searchBase = base == null ? "" : rewriteBase(base);
    String searchFilter = filter == null ? DEFAULT_FILTER : filter;

    Map<String, LscDatasets> res = new LinkedHashMap<String, LscDatasets>();

    if (attrsNames == null || attrsNames.size() == 0) {
        LOGGER.error("No attribute names to read! Check configuration.");
        return res;
    }//from   ww w.j  a v a 2  s. c  o  m

    String[] attributes = new String[attrsNames.size()];
    attributes = attrsNames.toArray(attributes);

    SearchControls constraints = new SearchControls();
    constraints.setDerefLinkFlag(false);
    constraints.setReturningAttributes(attributes);
    constraints.setSearchScope(scope);
    constraints.setReturningObjFlag(true);

    try {
        boolean requestPagedResults = false;

        List<Control> extControls = new ArrayList<Control>();

        if (pageSize > 0) {
            requestPagedResults = true;
            LOGGER.debug("Using pagedResults control for {} entries at a time", pageSize);
        }

        if (requestPagedResults) {
            extControls.add(new PagedResultsControl(pageSize, Control.CRITICAL));
        }

        if (sortedBy != null) {
            extControls.add(new SortControl(sortedBy, Control.CRITICAL));
        }

        if (extControls.size() > 0) {
            ctx.setRequestControls(extControls.toArray(new Control[extControls.size()]));
        }

        byte[] pagedResultsResponse = null;
        do {
            NamingEnumeration<SearchResult> results = ctx.search(searchBase, searchFilter, constraints);

            if (results != null) {
                Map<String, Object> attrsValues = null;
                while (results.hasMoreElements()) {
                    attrsValues = new HashMap<String, Object>();

                    SearchResult ldapResult = (SearchResult) results.next();

                    // get the value for each attribute requested
                    for (String attributeName : attrsNames) {
                        Attribute attr = ldapResult.getAttributes().get(attributeName);
                        if (attr != null && attr.get() != null) {
                            attrsValues.put(attributeName, attr.get());
                        }
                    }

                    res.put(ldapResult.getNameInNamespace(), new LscDatasets(attrsValues));
                }
            }

            Control[] respCtls = ctx.getResponseControls();
            if (respCtls != null) {
                for (Control respCtl : respCtls) {
                    if (requestPagedResults && respCtl instanceof PagedResultsResponseControl) {
                        pagedResultsResponse = ((PagedResultsResponseControl) respCtl).getCookie();
                    }
                }
            }

            if (requestPagedResults && pagedResultsResponse != null) {
                ctx.setRequestControls(new Control[] {
                        new PagedResultsControl(pageSize, pagedResultsResponse, Control.CRITICAL) });
            }

        } while (pagedResultsResponse != null);

        // clear requestControls for future use of the JNDI context
        if (requestPagedResults) {
            ctx.setRequestControls(null);
        }
    } catch (CommunicationException e) {
        // Avoid handling the communication exception as a generic one
        throw e;
    } catch (ServiceUnavailableException e) {
        // Avoid handling the service unavailable exception as a generic one
        throw e;
    } catch (NamingException e) {
        // clear requestControls for future use of the JNDI context
        ctx.setRequestControls(null);
        LOGGER.error(e.toString());
        LOGGER.debug(e.toString(), e);

    } catch (IOException e) {
        // clear requestControls for future use of the JNDI context
        ctx.setRequestControls(null);
        LOGGER.error(e.toString());
        LOGGER.debug(e.toString(), e);
    }
    return res;
}

From source file:org.nuxeo.ecm.directory.ldap.LDAPDirectory.java

/**
 * Search controls that only fetch attributes defined by the schema
 *
 * @return common search controls to use for all LDAP search queries
 * @throws DirectoryException//ww w .  ja v  a  2 s  .  c om
 */
protected SearchControls computeSearchControls() throws DirectoryException {
    LDAPDirectoryDescriptor ldapDirectoryDesc = getDescriptor();
    SearchControls scts = new SearchControls();
    // respect the scope of the configuration
    scts.setSearchScope(ldapDirectoryDesc.getSearchScope());

    // only fetch attributes that are defined in the schema or needed to
    // compute LDAPReferences
    Set<String> attrs = new HashSet<>();
    for (String fieldName : schemaFieldMap.keySet()) {
        if (!references.containsKey(fieldName)) {
            attrs.add(fieldMapper.getBackendField(fieldName));
        }
    }
    attrs.add("objectClass");

    for (Reference reference : getReferences()) {
        if (reference instanceof LDAPReference) {
            LDAPReference ldapReference = (LDAPReference) reference;
            attrs.add(ldapReference.getStaticAttributeId(fieldMapper));
            attrs.add(ldapReference.getDynamicAttributeId());

            // Add Dynamic Reference attributes filtering
            for (LDAPDynamicReferenceDescriptor dynAtt : ldapReference.getDynamicAttributes()) {
                attrs.add(dynAtt.baseDN);
                attrs.add(dynAtt.filter);
            }

        }
    }

    if (getPasswordField() != null) {
        // never try to fetch the password
        attrs.remove(getPasswordField());
    }

    scts.setReturningAttributes(attrs.toArray(new String[attrs.size()]));

    scts.setCountLimit(ldapDirectoryDesc.getQuerySizeLimit());
    scts.setTimeLimit(ldapDirectoryDesc.getQueryTimeLimit());

    return scts;
}

From source file:org.nuxeo.ecm.directory.ldap.LDAPDirectory.java

public SearchControls getSearchControls(boolean fetchAllAttributes) {
    if (fetchAllAttributes) {
        // return the precomputed scts instance
        return searchControls;
    } else {// w  w w  .ja  v a2  s.co  m
        // build a new ftcs instance with no attribute filtering
        LDAPDirectoryDescriptor ldapDirectoryDesc = getDescriptor();
        SearchControls scts = new SearchControls();
        scts.setSearchScope(ldapDirectoryDesc.getSearchScope());
        scts.setReturningAttributes(new String[] { ldapDirectoryDesc.rdnAttribute,
                ldapDirectoryDesc.fieldMapping.get(getIdField()) });
        return scts;
    }
}

From source file:org.nuxeo.ecm.directory.ldap.LDAPReference.java

/**
 * Fetch both statically and dynamically defined references and merge the results.
 *
 * @see org.nuxeo.ecm.directory.Reference#getSourceIdsForTarget(String)
 *///from   ww w  .j  a  v a 2  s .c om
@Override
public List<String> getSourceIdsForTarget(String targetId) throws DirectoryException {

    // container to hold merged references
    Set<String> sourceIds = new TreeSet<>();
    SearchResult targetLdapEntry = null;
    String targetDn = null;

    // step #1: resolve static references
    String staticAttributeId = getStaticAttributeId();
    if (staticAttributeId != null) {
        // step #1.1: fetch the dn of the targetId entry in the target
        // directory by the static dn valued strategy
        LDAPDirectory targetDir = getTargetLDAPDirectory();

        if (staticAttributeIdIsDn) {
            try (LDAPSession targetSession = (LDAPSession) targetDir.getSession()) {
                targetLdapEntry = targetSession.getLdapEntry(targetId, false);
                if (targetLdapEntry == null) {
                    String msg = String.format(
                            "Failed to perform inverse lookup on LDAPReference"
                                    + " resolving field '%s' of '%s' to entries of '%s'"
                                    + " using the static content of attribute '%s':"
                                    + " entry '%s' cannot be found in '%s'",
                            fieldName, sourceDirectory, targetDirectoryName, staticAttributeId, targetId,
                            targetDirectoryName);
                    throw new DirectoryEntryNotFoundException(msg);
                }
                targetDn = pseudoNormalizeDn(targetLdapEntry.getNameInNamespace());

            } catch (NamingException e) {
                throw new DirectoryException(
                        "error fetching " + targetId + " from " + targetDirectoryName + ": " + e.getMessage(),
                        e);
            }
        }

        // step #1.2: search for entries that reference that dn in the
        // source directory and collect their ids
        LDAPDirectory ldapSourceDirectory = getSourceLDAPDirectory();

        String filterExpr = String.format("(&(%s={0})%s)", staticAttributeId,
                ldapSourceDirectory.getBaseFilter());
        String[] filterArgs = new String[1];

        if (staticAttributeIdIsDn) {
            filterArgs[0] = targetDn;
        } else {
            filterArgs[0] = targetId;
        }

        String searchBaseDn = ldapSourceDirectory.getDescriptor().getSearchBaseDn();
        SearchControls sctls = ldapSourceDirectory.getSearchControls();
        try (LDAPSession sourceSession = (LDAPSession) ldapSourceDirectory.getSession()) {
            if (log.isDebugEnabled()) {
                log.debug(String.format(
                        "LDAPReference.getSourceIdsForTarget(%s): LDAP search search base='%s'"
                                + " filter='%s' args='%s' scope='%s' [%s]",
                        targetId, searchBaseDn, filterExpr, StringUtils.join(filterArgs, ", "),
                        sctls.getSearchScope(), this));
            }
            NamingEnumeration<SearchResult> results = sourceSession.dirContext.search(searchBaseDn, filterExpr,
                    filterArgs, sctls);

            try {
                while (results.hasMore()) {
                    Attributes attributes = results.next().getAttributes();
                    // NXP-2461: check that id field is filled
                    Attribute attr = attributes.get(sourceSession.idAttribute);
                    if (attr != null) {
                        Object value = attr.get();
                        if (value != null) {
                            sourceIds.add(value.toString());
                        }
                    }
                }
            } finally {
                results.close();
            }
        } catch (NamingException e) {
            throw new DirectoryException("error during reference search for " + filterArgs[0], e);
        }
    }
    // step #2: resolve dynamic references
    String dynamicAttributeId = this.dynamicAttributeId;
    if (dynamicAttributeId != null) {

        LDAPDirectory ldapSourceDirectory = getSourceLDAPDirectory();
        LDAPDirectory ldapTargetDirectory = getTargetLDAPDirectory();
        String searchBaseDn = ldapSourceDirectory.getDescriptor().getSearchBaseDn();

        try (LDAPSession sourceSession = (LDAPSession) ldapSourceDirectory.getSession();
                LDAPSession targetSession = (LDAPSession) ldapTargetDirectory.getSession()) {
            // step #2.1: fetch the target entry to apply the ldap url
            // filters of the candidate sources on it
            if (targetLdapEntry == null) {
                // only fetch the entry if not already fetched by the
                // static
                // attributes references resolution
                targetLdapEntry = targetSession.getLdapEntry(targetId, false);
            }
            if (targetLdapEntry == null) {
                String msg = String.format(
                        "Failed to perform inverse lookup on LDAPReference"
                                + " resolving field '%s' of '%s' to entries of '%s'"
                                + " using the dynamic content of attribute '%s':"
                                + " entry '%s' cannot be found in '%s'",
                        fieldName, ldapSourceDirectory, targetDirectoryName, dynamicAttributeId, targetId,
                        targetDirectoryName);
                throw new DirectoryException(msg);
            }
            targetDn = pseudoNormalizeDn(targetLdapEntry.getNameInNamespace());
            Attributes targetAttributes = targetLdapEntry.getAttributes();

            // step #2.2: find the list of entries that hold candidate
            // dynamic links in the source directory
            SearchControls sctls = ldapSourceDirectory.getSearchControls();
            sctls.setReturningAttributes(new String[] { sourceSession.idAttribute, dynamicAttributeId });
            String filterExpr = String.format("%s=*", dynamicAttributeId);

            if (log.isDebugEnabled()) {
                log.debug(String.format(
                        "LDAPReference.getSourceIdsForTarget(%s): LDAP search search base='%s'"
                                + " filter='%s' scope='%s' [%s]",
                        targetId, searchBaseDn, filterExpr, sctls.getSearchScope(), this));
            }
            NamingEnumeration<SearchResult> results = sourceSession.dirContext.search(searchBaseDn, filterExpr,
                    sctls);
            try {
                while (results.hasMore()) {
                    // step #2.3: for each sourceId and each ldapUrl test
                    // whether the current target entry matches the
                    // collected
                    // URL
                    Attributes sourceAttributes = results.next().getAttributes();

                    NamingEnumeration<?> ldapUrls = sourceAttributes.get(dynamicAttributeId).getAll();
                    try {
                        while (ldapUrls.hasMore()) {
                            LdapURL ldapUrl = new LdapURL(ldapUrls.next().toString());
                            String candidateDN = pseudoNormalizeDn(ldapUrl.getDN());
                            // check base URL
                            if (!targetDn.endsWith(candidateDN)) {
                                continue;
                            }

                            // check onelevel scope constraints
                            if ("onelevel".equals(ldapUrl.getScope())) {
                                int targetDnSize = new LdapName(targetDn).size();
                                int urlDnSize = new LdapName(candidateDN).size();
                                if (targetDnSize - urlDnSize > 1) {
                                    // target is not a direct child of the
                                    // DN of the
                                    // LDAP URL
                                    continue;
                                }
                            }

                            // check that the target entry matches the
                            // filter
                            if (getFilterMatcher().match(targetAttributes, ldapUrl.getFilter())) {
                                // the target match the source url, add it
                                // to the
                                // collected ids
                                sourceIds.add(sourceAttributes.get(sourceSession.idAttribute).get().toString());
                            }
                        }
                    } finally {
                        ldapUrls.close();
                    }
                }
            } finally {
                results.close();
            }
        } catch (NamingException e) {
            throw new DirectoryException("error during reference search for " + targetId, e);
        }
    }

    /*
     * This kind of reference is not supported because Active Directory use filter expression not yet supported by
     * LDAPFilterMatcher. See NXP-4562
     */
    if (dynamicReferences != null && dynamicReferences.length > 0) {
        log.error("This kind of reference is not supported.");
    }

    return new ArrayList<>(sourceIds);
}

From source file:org.nuxeo.ecm.directory.ldap.LDAPReference.java

/**
 * Retrieve the elements referenced by the filter/BaseDN/Scope request.
 *
 * @param attributes Attributes of the referencer element
 * @param directoryDn Dn of the Directory
 * @param linkDn Dn specified in the parent
 * @param filter Filter expression specified in the parent
 * @param scope scope for the search// w  w  w.j  a  va 2 s .  c  om
 * @return The list of the referenced elements.
 * @throws DirectoryException
 * @throws NamingException
 */
private Set<String> getReferencedElements(Attributes attributes, String directoryDn, String linkDn,
        String filter, int scope) throws DirectoryException, NamingException {

    Set<String> targetIds = new TreeSet<>();

    LDAPDirectoryDescriptor targetDirconfig = getTargetDirectoryDescriptor();
    LDAPDirectory ldapTargetDirectory = (LDAPDirectory) getTargetDirectory();
    LDAPSession targetSession = (LDAPSession) ldapTargetDirectory.getSession();

    // use the most specific scope between the one specified in the
    // Directory and the specified in the Parent
    String dn = directoryDn.endsWith(linkDn) && directoryDn.length() > linkDn.length() ? directoryDn : linkDn;

    // combine the ldapUrl search query with target
    // directory own constraints
    SearchControls scts = new SearchControls();

    // use the most specific scope
    scts.setSearchScope(Math.min(scope, targetDirconfig.getSearchScope()));

    // only fetch the ids of the targets
    scts.setReturningAttributes(new String[] { targetSession.idAttribute });

    // combine the filter of the target directory with the
    // provided filter if any
    String targetFilter = targetDirconfig.getSearchFilter();
    if (filter == null || filter.length() == 0) {
        filter = targetFilter;
    } else if (targetFilter != null && targetFilter.length() > 0) {
        filter = String.format("(&(%s)(%s))", targetFilter, filter);
    }

    // perform the request and collect the ids
    if (log.isDebugEnabled()) {
        log.debug(String.format(
                "LDAPReference.getLdapTargetIds(%s): LDAP search dn='%s' " + " filter='%s' scope='%s' [%s]",
                attributes, dn, dn, scts.getSearchScope(), this));
    }

    Name name = new CompositeName().add(dn);
    NamingEnumeration<SearchResult> results = targetSession.dirContext.search(name, filter, scts);
    try {
        while (results.hasMore()) {
            // NXP-2461: check that id field is filled
            Attribute attr = results.next().getAttributes().get(targetSession.idAttribute);
            if (attr != null) {
                String collectedId = attr.get().toString();
                if (collectedId != null) {
                    targetIds.add(collectedId);
                }
            }

        }
    } finally {
        results.close();
    }

    return targetIds;
}

From source file:org.nuxeo.ecm.directory.ldap.LDAPReference.java

/**
 * Remove existing statically defined links for the given target id (dynamic references remain unaltered)
 *
 * @see org.nuxeo.ecm.directory.Reference#removeLinksForTarget(String)
 *//*from  www  .j a  v a2  s. co  m*/
@Override
public void removeLinksForTarget(String targetId) throws DirectoryException {
    if (!isStatic()) {
        // nothing to do: dynamic references cannot be updated
        return;
    }
    LDAPDirectory ldapTargetDirectory = (LDAPDirectory) getTargetDirectory();
    LDAPDirectory ldapSourceDirectory = (LDAPDirectory) getSourceDirectory();
    String attributeId = getStaticAttributeId();
    try (LDAPSession targetSession = (LDAPSession) ldapTargetDirectory.getSession();
            LDAPSession sourceSession = (LDAPSession) ldapSourceDirectory.getSession()) {
        if (!sourceSession.isReadOnly()) {
            // get the dn of the target that matches targetId
            String targetAttributeValue;

            if (staticAttributeIdIsDn) {
                SearchResult targetLdapEntry = targetSession.getLdapEntry(targetId);
                if (targetLdapEntry == null) {
                    String rdnAttribute = ldapTargetDirectory.getDescriptor().getRdnAttribute();
                    if (!rdnAttribute.equals(targetSession.idAttribute)) {
                        log.warn(String.format(
                                "cannot remove links to missing entry %s in directory %s for reference %s",
                                targetId, ldapTargetDirectory.getName(), this));
                        return;
                    }
                    // the entry might have already been deleted, try to
                    // re-forge it if possible (might not work if scope is
                    // subtree)
                    targetAttributeValue = String.format("%s=%s,%s", rdnAttribute, targetId,
                            ldapTargetDirectory.getDescriptor().getSearchBaseDn());
                } else {
                    targetAttributeValue = pseudoNormalizeDn(targetLdapEntry.getNameInNamespace());
                }
            } else {
                targetAttributeValue = targetId;
            }

            // build a LDAP query to find entries that point to the target
            String searchFilter = String.format("(%s=%s)", attributeId, targetAttributeValue);
            String sourceFilter = ldapSourceDirectory.getBaseFilter();

            if (sourceFilter != null && !"".equals(sourceFilter)) {
                searchFilter = String.format("(&(%s)(%s))", searchFilter, sourceFilter);
            }

            SearchControls scts = new SearchControls();
            scts.setSearchScope(ldapSourceDirectory.getDescriptor().getSearchScope());
            scts.setReturningAttributes(new String[] { attributeId });

            // find all source entries that point to the target key and
            // clean
            // those references
            if (log.isDebugEnabled()) {
                log.debug(String.format(
                        "LDAPReference.removeLinksForTarget(%s): LDAP search baseDn='%s' "
                                + " filter='%s' scope='%s' [%s]",
                        targetId, sourceSession.searchBaseDn, searchFilter, scts.getSearchScope(), this));
            }
            NamingEnumeration<SearchResult> results = sourceSession.dirContext
                    .search(sourceSession.searchBaseDn, searchFilter, scts);
            String emptyRefMarker = ldapSourceDirectory.getDescriptor().getEmptyRefMarker();
            Attributes emptyAttribute = new BasicAttributes(attributeId, emptyRefMarker);

            try {
                while (results.hasMore()) {
                    SearchResult result = results.next();
                    Attributes attrs = result.getAttributes();
                    Attribute attr = attrs.get(attributeId);
                    try {
                        if (attr.size() == 1) {
                            // the attribute holds the last reference, put
                            // the
                            // empty ref. marker before removing the
                            // attribute
                            // since empty attribute are often not allowed
                            // by
                            // the server schema
                            if (log.isDebugEnabled()) {
                                log.debug(String.format(
                                        "LDAPReference.removeLinksForTarget(%s): LDAP modifyAttributes key='%s' "
                                                + "mod_op='ADD_ATTRIBUTE' attrs='%s' [%s]",
                                        targetId, result.getNameInNamespace(), attrs, this));
                            }
                            sourceSession.dirContext.modifyAttributes(result.getNameInNamespace(),
                                    DirContext.ADD_ATTRIBUTE, emptyAttribute);
                        }
                        // remove the reference to the target key
                        attrs = new BasicAttributes();
                        attr = new BasicAttribute(attributeId);
                        attr.add(targetAttributeValue);
                        attrs.put(attr);
                        if (log.isDebugEnabled()) {
                            log.debug(String.format(
                                    "LDAPReference.removeLinksForTarget(%s): LDAP modifyAttributes key='%s' "
                                            + "mod_op='REMOVE_ATTRIBUTE' attrs='%s' [%s]",
                                    targetId, result.getNameInNamespace(), attrs, this));
                        }
                        sourceSession.dirContext.modifyAttributes(result.getNameInNamespace(),
                                DirContext.REMOVE_ATTRIBUTE, attrs);
                    } catch (SchemaViolationException e) {
                        if (isDynamic()) {
                            // we are editing an entry that has no static
                            // part
                            log.warn(String.format("cannot remove dynamic reference in field %s for target %s",
                                    getFieldName(), targetId));
                        } else {
                            // this is a real schema configuration problem,
                            // wrapup the exception
                            throw new DirectoryException(e);
                        }
                    }
                }
            } finally {
                results.close();
            }
        }
    } catch (NamingException e) {
        throw new DirectoryException("removeLinksForTarget failed: " + e.getMessage(), e);
    }
}