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

📄 ldifutility.java

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

import javax.naming.*;
import javax.naming.directory.*;

import java.util.*;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.io.*;

import com.ca.commons.cbutil.*;



/**
 * collection of static utility ftns. for
 * writing and reading ldif files.  Currently does not
 * handle URLs properly, but will do base64 encoding
 * quite happily given half a chance...
 */

//TODO: add 'version 2' handling to ldif file when using xml / ldif, and setup config parameter.

public class LdifUtility
{
    private static boolean debug = false;

    private static boolean handleXML = false;

    private Hashtable params = null;	// list of expandable strings for the ldif file, used during file parsing
    // e.g. KEY: <base_dn>, KEY VALUE: "o=eTrust, cn=Users"
    private String filedir = null;

    private String cr = System.getProperty("line.separator", "\n");

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

    public LdifUtility()
    {
    }

    /**
     * Sets whether to support the draft rfc for special handling of XML data in LDIF files.
     * @param state
     */
    public static void setSupportXML_LDIF_RFC(boolean state)
    {
        handleXML = state;
    }

    /**
     * Constructor
     *
     * @param params  - hashtable with the list of string that will have to be suvstituted in the ldif file
     * @param filedir - ldif file directory, used to find the input files specified in the ldif stream
     */
    public LdifUtility(Hashtable params, String filedir)
    {
        this.params = params;
        this.filedir = filedir;
    }

    /**
     * Set the ldif filepath - used to find input files
     *
     * @param filedir file path
     */
    public void setFileDir(String filedir)
    {
        this.filedir = filedir + "\\";
    }

    /**
     * Set the ldif file parameters
     *
     * @param params list of parameters
     */
    public void setParams(Hashtable params)
    {
        this.params = params;
    }

    /**
     * This is used to write a value that is *probably* normal
     * string encoded, but *may* need to be base64 encoded.
     * It also takes a boolean parameter that forces base64 encoding.
     * Otherwise, it
     * checks the string against the requirements of draft-good-ldap-ldif-04
     * (initial character sane, subsequent characters not null, CR or LF),
     * and returns the appropriate string, with appropriate ': ' or ':: '
     * prefix.
     *
     * @param o the object to be ldif encoded
     * @return the ldif encoding (possibly base64) with appropriate colons.
     */
    public String ldifEncode(Object o, int offset, boolean forceBase64Encoding)
    {
        if (forceBase64Encoding == false)
            return ldifEncode(o, offset);

        String ret = ":: ";
        if (o.getClass().isArray())
        {
            try
            {
                byte b[] = (byte[]) o;
                ret += CBBase64.binaryToString(b, offset + 3);
                return ret;
            }
            catch (ClassCastException e)
            {
                System.out.println("unable to cast array to byte array.");
            }
        }
        
        // it's not a byte array; force it to a string, read as bytes,
        // and code those.  This will work in most cases, but will 
        // fail badly for isNonString data that has not been encoded properly
        // already; e.g. a gif file should (probably) be translated to a 
        // byte array before being passed to this ftn.    
        
        ret += CBBase64.binaryToString(o.toString().getBytes(), offset + 3);
        return ret;
    }

    /**
     * This is used to write a value that is *probably* normal
     * string encoded, but *may* need to be base64 encoded or xml encoded.  It
     * checks the string against the requirements of draft-good-ldap-ldif-04
     * (initial character sane, subsequent characters not null, CR or LF),
     * and returns the appropriate string, with appropriate ': ' or ':: '
     * prefix.  It also supports the draft 'Extended LDAP Data Interchange Foramt'
     * handling of xml text that is identified by an initial '<?xml ' string.
     *
     * @param o      the object to be ldif encoded
     * @param offset The first line of the string may be offset by
     *               by this many characters for nice formatting (e.g. in
     *               an ldif file, the first line may include 'att value = ...'
     *               at the beginning of the base 64 encoded block).
     * @return the ldif encoding (possibly base64) with appropriate colons.
     */

    public String ldifEncode(Object o, int offset)
    {
        boolean base64Encode = false;

        boolean xmlEncode = false;

        if ((o instanceof String) == false)
        {
            if (debug == true) System.out.println("found a " + o.getClass().toString());
            if (o.getClass().isArray())
            {
                try
                {
                    byte b[] = (byte[]) o;
                    String ret = ":: " + CBBase64.binaryToString(b, offset + 3);
                    if (debug == true) System.out.println("phenomenal - identified and wrote '" + ret + "'");
                    return ret;
                }
                catch (ClassCastException e)
                {
                    if (debug == true) System.out.println("unable to cast array to byte array.");
                }
            }
            return o.toString();
        }
        else    // we have a string
        {
            String s = o.toString();
            int len = s.length();

            if (len == 0) return ": ";  // this shouldn't really happen; null attributes should be culled before we get here...


            // run the rfc tests to see if this is a good and virtuous string
            char startChar = s.charAt(0);
            if ("\n\r :".indexOf(startChar) != -1)    // check for safe start char
                base64Encode = true;
            else if (startChar == '<')
            {
                if (handleXML == true && s.startsWith("<?xml "))  // we have xml text, and will cope with wierd characters differently.
                    xmlEncode = true;
                else
                    base64Encode = true;
            }
            else
            {
                char test[] = new char[len];
                s.getChars(0, len, test, 0);
                for (int i = 0; i < len; i++)
                {
                    //System.out.println("checking: " + i + ": " + test[i] + " = " + CBUtility.charToHex(test[i]));
                    if (test[i] > 126 || test[i] < 32)    // check for sane intermediate chars
                    {
                        base64Encode = true;          // (may be unicode international string)
                        break;
                    }
                }
            }

            if (s.charAt(s.length() - 1) == ' ')        // end space considered harmful
                base64Encode = true;

            if (base64Encode)
            {
                return translateToLdifBase64(s, offset);
            }
            else if (xmlEncode)
                return translateToLdifXML(s);
            else
                return ": " + s;                        // return unmodified string.
        }
    }

    private String translateToLdifBase64(String s, int offset)
    {
        try
        {
            s = CBBase64.binaryToString(s.getBytes("UTF8"), offset + 3);
        }
        catch (UnsupportedEncodingException e) // why would we get this when utf8 is mandatory across all java platforms?
        {
            log.log(Level.WARNING, "error utf8 encoding strings...", e);
            s = CBBase64.binaryToString(s.getBytes(), offset + 3);
        }
        return ":: " + s;
    }

    /**
     * This replaces new lines (of various sorts) with a 'new line' + '>' character, as per 'xml in ldif' draft rfc.
     * @param s
     * @return
     */
    private String translateToLdifXML(String s)
    {
        StringBuffer xml = new StringBuffer(";transfer-rxer>:").append(cr).append(s);

        // carriage return madness :-(.  Runs fastest on systems that use '\n' only.  Seems about right.

        if (s.indexOf("\r") != -1)  // mac (I think)
        {
            CBParse.replaceAllBufferString(xml, "\r", "\r>");
        }
        if (s.indexOf("\n") != -1)  // catches both '\r\n' and '\n'
        {
            CBParse.replaceAllBufferString(xml, "\n", "\n>");
        }

        return xml.toString();
    }

    /**
     *    Writes a single ldif entry...
     *
     */
    /**
     * retrieves a single entry from the directory and writes it
     * out to an ldif file.  Note that ldif header 'version 1' must
     * be written elsewhere...
     *
     * @param dn                the ldap escaped dn of the entry being written
     * @param saveFile          the file to write the entry to
     * @param originalPrefix    an optional portion of the dn to update
     * @param replacementPrefix an optional replacement for a portion of the dn
     * @param atts              the attributes of teh entry
     */

    public void writeLdifEntry(String dn, FileWriter saveFile, String originalPrefix, String replacementPrefix, Attributes atts)
            throws NamingException, IOException
    {
        if (atts == null)
        {
            log.info("no attributes available for " + dn);
            return;
        }
        /**
         *    Prefix replacement magic.  If we are moving the tree during
         *    the save, and a different prefix has been given (i.e. the
         *    originalPrefix and replacementPrefix variables aren't zero)
         *    we switch the relavent portion of the saved dn, substituting
         *    the portion of the dn that contains the original prefix with
         *    the replacement.
         *    e.g. cn=Fredo,o=FrogFarm,c=au, with original prefix o=FrogFarm,c=au
         *         and replacement o=FreeFrogs,c=au, becomes cn=Fredo,o=FreeFrogs,c=au
         */
        if ((originalPrefix != null) && (dn.endsWith(originalPrefix))) // which it jolly well should...
        {
            if (debug == true) System.out.println("original DN = '" + dn + "'");
            dn = dn.substring(0, dn.length() - originalPrefix.length()) + replacementPrefix;
            if (debug == true) System.out.println("after replacement DN = '" + dn + "'");
        }

        Attribute oc;        // we treat the object class attribute
        oc = atts.get("oc"); // specially to ensure it is first after the dn.
        if (oc != null)      // XXX do a name conversion...
        {
            if (oc instanceof DXAttribute)
                ((DXAttribute) oc).setName("objectClass");
        }
        else                 // (mind you its bloody hard to track down...!)
            oc = atts.get("objectclass");  // so keep looking...
        if (oc == null)
            oc = atts.get("objectClass"); // this really bites.
        if (oc == null)
        {
            if (dn.endsWith("cn=schema"))  // XXX el dirty hack to allow schema to be sorta written out...
                oc = new BasicAttribute("oc", "schema");
        }

        if (oc == null)
        {
            log.info("unable to identify object class for " + dn + " - skipping entry");
            return;
        }

        if (debug)
            System.out.println("dn" + ldifEncode(dn, 2));
        else
            saveFile.write("dn" + ldifEncode(dn, 2) + "\n");


        NamingEnumeration ocs = oc.getAll();
        while (ocs.hasMore())
        {
            if (debug)
                System.out.println(oc.getID() + ": " + ocs.next());
            else
                saveFile.write(oc.getID() + ldifEncode(ocs.next(), oc.getID().length()) + "\n");
        }

        NamingEnumeration allAtts = atts.getAll();
        String attName;
        Attribute currentAtt;
        while (allAtts.hasMore())
        {

⌨️ 快捷键说明

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