⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsmlcontext.java

📁 JAVA开源LDAP浏览器jxplorer的源码!
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
package com.ca.jndiproviders.dsml;

import com.ca.commons.naming.DXNamingEnumeration;
import com.ca.commons.naming.DN;
import com.ca.commons.cbutil.CBBase64;
import com.ca.commons.cbutil.CBBase64EncodingException;

import javax.naming.directory.*;
import javax.naming.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.io.UnsupportedEncodingException;
import java.io.IOException;

/**
 * <p>This is a DSML jndiproviders context, that provides support for all the basic DSML operations.</p>
 * <p/>
 * <p>However, it deliberately does *not* support:</p>
 * <ul>
 * <li>binding java objects - the bind methods are not implemented.  Users will need to do their
 * own serialisation if they want this functionality.
 * <li> referrals aren't implemented yet.
 * <li> ldap v3 extensions.
 * <li> composite names spanning multiple namespaces - all names are DSML names only.  (Composite
 * names are a bloody stupid idea that come close to making jndiproviders unusable, IMNSHO - CB)
 * </ul>
 * <p/>
 * <p>If you need the above features, you may be better off using the Sun DSML provider which is
 * far more ambitious in scope (but which has some licencing problems, and is a bit rocky in parts).</p>
 */

/*
 *   DSML SERVER ERROR NOTES
 *
 *   Server is incorrectly parsing escaped dns - e.g. dn="cn=Vivienne \"LEVER\", ... ".
 *   Server is returning HTTP 500, which prevents parsing of returned soap error
 *
 */


//TODO: schema support??

//TODO: we ended up using strings rather than names, so adjust all methods to chain to the string methods instead of the name methods.

//TODO: makes heavy use of static stuff - may not be thread safe.

public class DsmlContext implements DirContext
{

    // Formatting
    private static int TABLEN = 4;
    private static String TAB = "    ";
    private static String TAB2 = TAB + TAB;
    private static String TAB3 = TAB2 + TAB;
    private static String TAB4 = TAB3 + TAB;
    private static String TAB5 = TAB4 + TAB;
    private static String TAB6 = TAB5 + TAB;

    private static String SOAPHEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            TAB + "<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
            TAB2 + "<soap-env:Body>\n";

    private static String SOAPFOOTER = TAB2 + "</soap-env:Body>\n" +
            TAB + "</soap-env:Envelope>";

    private static String DSMLHEADER = TAB3 + "<dsml:batchRequest xmlns:dsml=\"urn:oasis:names:tc:DSML:2:0:core\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";

    private static String DSMLFOOTER = TAB3 + "</dsml:batchRequest>\n";

    private static String SEARCHFOOTER = TAB3 + "</dsml:searchRequest>\n";

    private static String STANDARDHEADER = SOAPHEADER + DSMLHEADER;

    private static String STANDARDFOOTER = DSMLFOOTER + SOAPFOOTER;

    // SEARCH SCOPE CONSTANTS
    private static String BASEOBJECT = "baseObject";
    private static String SINGLELEVEL = "singleLevel";
    private static String WHOLESUBTREE = "wholeSubtree";
    private static String[] SCOPEOPTIONS = new String[]{BASEOBJECT, SINGLELEVEL, WHOLESUBTREE};

    // SEARCH ALIAS DEREF OPTIONS
    private static String NEVER = "neverDerefAliases";
    private static String SEARCHING = "derefInSearching";
    private static String FINDING = "derefFindingBaseObj";
    private static String ALWAYS = "derefAlways";
    private static String[] ALIASOPTIONS = new String[]{NEVER, SEARCHING, FINDING, ALWAYS};

    // Default Search Controls
    private static SearchControls DEFAULT_SEARCH_CONTROLS = new SearchControls();


    protected Hashtable environment;

    // the name of the context (as set by 'createSubcontext' methods
    private String contextName = "";

    private static Logger log = Logger.getLogger(DsmlContext.class.getName());

    // Debug
    {
        log.setLevel(Level.FINEST);
    }

    /**
     * <p>This constructs the XML tag and tag attributes for a DSML search operation start tag.  (filter and attributes elements
     * must be added separately, the end tag is a defined constant.)
     * <p/>
     * <p>e.g.
     * <pre>
     * &lt;dsml:searchRequest requestID="1" dn="cn=schema" scope="baseObject" derefAliases="derefInSearching"&gt;
     * </pre>
     * <p/>
     * something like
     *
     * @param searchHeader an existing string buffer to append the search header information in.
     * @param dn           the dn to search from
     * @param scope        the search scope, must be one of 'baseLevel', 'singleLevel' or 'wholeSubtree' (see constants)
     * @param derefAliases how to handle aliases.  must be on of 'neverDerefAliases', 'derefInSearching', 'derefFindingBaseObj', 'derefAlways' (see constants)
     * @param sizeLimit    the LDAP search size limit - default is 0 (unlimited by client)
     * @param timeLimit    the LDAP search time limit - default is 0 (unlimited by client)
     * @param typesOnly    - no idea, but it's in the spec.
     * @return a string buffer containing the raw xml for a search operation.
     * @throws NamingException
     */
    private static StringBuffer getSearchRequestHeader(StringBuffer searchHeader, String dn, String scope, String derefAliases, long sizeLimit, int timeLimit, boolean typesOnly)
            throws NamingException
    {
        // sanity check arguments
        if (!checkValidity(SCOPEOPTIONS, scope))
            throw new NamingException("search scope argument '" + scope + "' is invalid");

        if (!checkValidity(ALIASOPTIONS, derefAliases))
        {
            if (derefAliases != null) log.info("bad alias option passed '" + derefAliases + "'");
            derefAliases = SEARCHING;
        }

        if (searchHeader == null)
            searchHeader = new StringBuffer();

        searchHeader.append(TAB4 + "<dsml:searchRequest dn=\"");     // TODO: requestID is optional - let's drop it in the final version - CB
        searchHeader.append(escapeName(dn));
        searchHeader.append("\" scope=\"").append(scope);
        searchHeader.append("\" derefAliases=\"").append(derefAliases);

        if (sizeLimit > 0)
            searchHeader.append("\" sizeLimit=\"").append(sizeLimit);

        if (timeLimit > 0)
            searchHeader.append("\" timeLimit=\"").append(timeLimit);

        // never used?
        if (typesOnly == true)
            searchHeader.append("\" typesOnly=\"").append(typesOnly);

        searchHeader.append("\">\n");

        log.finest("created search header: " + searchHeader);

        return searchHeader;
    }


    /**
     * <p>This constructs the XML tag and elements for a DSML search attribute list
     * <p/>
     * e.g.
     * <pre>
     * &gt;dsml:attributes&lt;
     * &gt;dsml:attribute name="attributeTypes"/&lt;
     * &gt;dsml:attribute name="objectClasses"/&lt;
     * &gt;dsml:attribute name="matchingRules"/&lt;
     * &gt;dsml:attribute name="ldapSyntaxes"/&lt;
     * &gt;dsml:attribute name="*"/&lt;
     * &gt;/dsml:attributes&lt;
     * </pre>
     *
     * @param searchAttributes an existing string buffer to append the search attribute list information to
     * @param attributes       a string array of attribute names
     * @return
     */
    private static StringBuffer getSearchRequestAttributes(StringBuffer searchAttributes, String[] attributes)
    {
        if (attributes == null || attributes.length == 0)
        {
            return searchAttributes;  // do nothing if there are no specific attributes (means return all)
        }

        if (searchAttributes == null)
            searchAttributes = new StringBuffer(40 + 80 * attributes.length);

        searchAttributes.append(TAB5 + "<dsml:attributes>\n");

        int len = attributes.length;
        for (int i = 0; i < len; i++)
        {
            searchAttributes.append(TAB6 + "<dsml:attribute name=\"").append(attributes[i]).append("\"/>\n");
        }

        searchAttributes.append(TAB5 + "</dsml:attributes>\n");

        log.finest("created search attribute list: " + searchAttributes);

        return searchAttributes;
    }


    /**
     * Small utility method to check that a string is one of a number of valid options.
     *
     * @param options an array of valid options.
     * @param checkme a string to compare against the previous array.
     * @return true if checkme is one of the options, false if it is null, or is not one of the options.
     */
    private static boolean checkValidity(String[] options, String checkme)
    {
        if (checkme != null)
        {
            for (int i = 0; i < options.length; i++)
                if (options[i].equals(checkme))
                    return true;
        }
        return false;
    }

    /**
     * A little test method to produce dummy enumerations during development
     *
     * @param name
     * @param num
     * @return
     */
    private NamingEnumeration getTestEnumeration(Name name, int num)
    {
        log.finest("generating " + num + " test names from '" + name.toString() + "'");

        String itemBase = "c=AU";
        if (name.size() == 1)
            itemBase = "o=beta";
        else if (name.size() == 2)
            itemBase = "ou=gamma";
        else if (name.size() == 3)
            itemBase = "ou=delta";

        DXNamingEnumeration testEnumeration = new DXNamingEnumeration();
        for (int i = 0; i < num; i++)
        {
            String itemName = itemBase + i;
            testEnumeration.add(new SearchResult(itemName, null, getTestAttributes(itemName)));
        }

        return testEnumeration;
    }

    /**
     * A little test method to produce dummy attributes objects during development.
     *
     * @param name
     * @return
     */
    private BasicAttributes getTestAttributes(String name)
    {
        log.finest("generating test data from name '" + name + "'");
        BasicAttributes testAttributes = new BasicAttributes("cn", name);
        testAttributes.put(new BasicAttribute("objectClass", "person"));
        testAttributes.put(new BasicAttribute("sn", "Test"));
        return testAttributes;
    }

    private DsmlContext()
    {
    }  // don't do this :-).


    private DsmlContext(String baseDN, Hashtable env)
    {
        contextName = baseDN==null?"":baseDN;

        environment = env;     // Don't see any reason to clone environment for every entry?
    }

    /**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -