public Rdn[] getRelativeDNFromResult( SearchResult answer ) throws NamingException
    {
        // All other methods assume that UserDN is a relative distinguished name,
        // not a (full) distinguished name. However if a referral was followed,
        // a DN instead of a RDN value is returned. The following code converts
        // a referral back to a RDN (previously referred to as a "partial" LDAP
        // string).
        if (!answer.isRelative()) {
            final LdapName dn = new LdapName(( answer.getName() ));
            final List<Rdn> rdns = dn.getRdns();
            return new Rdn[] { rdns.get( rdns.size() -1) };
        }

        // Occasionally, the name is returned as: "cn=ship crew/cooks" (a string
        // that starts with a quote). This likely occurs when the value contains
        // characters that are invalid when not escaped.
        //
        // Quotes around the entire name cannot be parsed (unlike, for example:
        // cn="ship crew/cooks", where the value component, rather than the
        // entire name, is put in quotes).
        //
        // When quotes are detected, this method will strip them, and apply
        // instead escaping according to the rules specified in
        // <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>. This is
        // designed to prevent quotes, or otherwise escaped values from showing
        // in Openfire user and group names.
        Log.debug("Processing relative LDAP SearchResult: '{}'", answer);
        String name = answer.getName();
        boolean needsEscaping = false;
        if ( name.startsWith("\"") && name.endsWith("\"") )
        {
            // Strip off the leading and trailing quote.
            Log.debug("SearchResult was quote-wrapped: '{}'", name);
            name = name.substring(1, name.length()-1 );
            needsEscaping = true;
        }

        if (!needsEscaping)
        {
            // The search result contains a JNDI composite name. From this, a DN needs to be extracted before it can be processed further.
            // See https://bugs.openjdk.java.net/browse/JDK-6201615?focusedCommentId=12344311&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-12344311
            final Name cname = new CompositeName(name);
            name = cname.get(0);
        }

        // Split the search result, which is a relative distinguished name, into separate Rdn values, using a regular expression.
        //
        // This regex is designed to:
        // - split the input string on a comma character,
        // - except for when the comma is escaped (preceded by a \). The regex uses a negative look-behind to detect this case.
        // - The comma needs to be followed by one or more letters, which themselves need to be followed by an equal sign,
        //   which must be followed by at least one other character.
        final String[] rdns = name.split("(?<![\\\\]),(?=[a-zA-z]+=.+)");

        final List<Rdn> result = new ArrayList<>();
        for (String rdn : rdns)
        {
            // If the entire value was in quotes, each individual RDN needs escaping.
            if ( needsEscaping )
            {
                // Escape the value (but first split off the type, to prevent the '=' character from being escaped).
                final String[] typeValue = rdn.split("=",2);
                if (typeValue.length != 2) {
                    Log.warn("Unexpected value while parsing a RDN: '{}'.", name);
                } else {
                    name = typeValue[0] + "=" + Rdn.escapeValue(typeValue[1]);
                    result.add( new Rdn(name) );
                }
            }
            else
            {
                result.add(new Rdn(rdn));
            }
        }

        return result.toArray(new Rdn[0]);
    }
Returns a RDN from the search result answer. The return value consists of
one or more Rdn instances, that, when combined, are relative to the base
DN that was used for the search.

@param answer The result of the search (cannot be null).
@return A relative distinguished name from the answer.
@throws NamingException When the search result value cannot be used to form a valid RDN value.
xmppserver/src/main/java/org/jivesoftware/openfire/ldap/LdapManager.java