edu.vt.middleware.ldap.ldif.Ldif.java Source code

Java tutorial

Introduction

Here is the source code for edu.vt.middleware.ldap.ldif.Ldif.java

Source

/*
  $Id$
    
  Copyright (C) 2003-2010 Virginia Tech.
  All rights reserved.
    
  SEE LICENSE FOR MORE INFORMATION
    
  Author:  Middleware Services
  Email:   middleware@vt.edu
  Version: $Revision$
  Updated: $Date$
*/
package edu.vt.middleware.ldap.ldif;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.Writer;
import java.net.URL;
import java.util.Iterator;
import javax.naming.NamingException;
import javax.naming.directory.SearchResult;
import edu.vt.middleware.ldap.LdapUtil;
import edu.vt.middleware.ldap.bean.LdapAttribute;
import edu.vt.middleware.ldap.bean.LdapBeanFactory;
import edu.vt.middleware.ldap.bean.LdapBeanProvider;
import edu.vt.middleware.ldap.bean.LdapEntry;
import edu.vt.middleware.ldap.bean.LdapResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * <code>Ldif</code> contains functions for converting LDAP search result sets
 * into LDIF.
 *
 * @author  Middleware Services
 * @version  $Revision$ $Date$
 */
public class Ldif implements Serializable {

    /** ASCII decimal value of nul. */
    public static final int NUL_CHAR = 0;

    /** ASCII decimal value of line feed. */
    public static final int LF_CHAR = 10;

    /** ASCII decimal value of carriage return. */
    public static final int CR_CHAR = 13;

    /** ASCII decimal value of space. */
    public static final int SP_CHAR = 32;

    /** ASCII decimal value of colon. */
    public static final int COLON_CHAR = 58;

    /** ASCII decimal value of left arrow. */
    public static final int LA_CHAR = 60;

    /** ASCII decimal value of highest character. */
    public static final int MAX_ASCII_CHAR = 127;

    /** serial version uid. */
    private static final long serialVersionUID = -3763879179455001975L;

    /** Line separator. */
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");

    /** Log for this class. */
    protected final Log logger = LogFactory.getLog(this.getClass());

    /** Ldap bean factory. */
    protected LdapBeanFactory beanFactory = LdapBeanProvider.getLdapBeanFactory();

    /**
     * Returns the factory for creating ldap beans.
     *
     * @return  <code>LdapBeanFactory</code>
     */
    public LdapBeanFactory getLdapBeanFactory() {
        return this.beanFactory;
    }

    /**
     * Sets the factory for creating ldap beans.
     *
     * @param  lbf  <code>LdapBeanFactory</code>
     */
    public void setLdapBeanFactory(final LdapBeanFactory lbf) {
        if (lbf != null) {
            this.beanFactory = lbf;
        }
    }

    /**
     * This will take the results of a prior LDAP query and convert it to LDIF.
     *
     * @param  results  <code>Iterator</code> of LDAP search results
     *
     * @return  <code>String</code>
     */
    public String createLdif(final Iterator<SearchResult> results) {
        String ldif = "";
        try {
            final LdapResult lr = this.beanFactory.newLdapResult();
            lr.addEntries(results);
            ldif = this.createLdif(lr);
        } catch (NamingException e) {
            if (this.logger.isErrorEnabled()) {
                this.logger.error("Error creating String from SearchResults", e);
            }
        }
        return ldif;
    }

    /**
     * This will take the results of a prior LDAP query and convert it to LDIF.
     *
     * @param  result  <code>LdapResult</code>
     *
     * @return  <code>String</code>
     */
    public String createLdif(final LdapResult result) {
        // build string from results
        final StringBuffer ldif = new StringBuffer();
        if (result != null) {
            for (LdapEntry le : result.getEntries()) {
                ldif.append(createLdifEntry(le));
            }
        }

        return ldif.toString();
    }

    /**
     * This will take an LDAP entry and convert it to LDIF.
     *
     * @param  ldapEntry  <code>LdapEntry</code> to convert
     *
     * @return  <code>String</code>
     */
    protected String createLdifEntry(final LdapEntry ldapEntry) {
        final StringBuffer entry = new StringBuffer();
        if (ldapEntry != null) {

            final String dn = ldapEntry.getDn();
            if (dn != null) {
                if (encodeData(dn)) {
                    final String encodedDn = LdapUtil.base64Encode(dn);
                    if (encodedDn != null) {
                        entry.append("dn:: ").append(dn).append(LINE_SEPARATOR);
                    }
                } else {
                    entry.append("dn: ").append(dn).append(LINE_SEPARATOR);
                }
            }

            for (LdapAttribute attr : ldapEntry.getLdapAttributes().getAttributes()) {
                final String attrName = attr.getName();
                for (Object attrValue : attr.getValues()) {
                    if (encodeData(attrValue)) {
                        String encodedAttrValue = null;
                        if (attrValue instanceof String) {
                            encodedAttrValue = LdapUtil.base64Encode((String) attrValue);
                        } else if (attrValue instanceof byte[]) {
                            encodedAttrValue = LdapUtil.base64Encode((byte[]) attrValue);
                        } else {
                            if (this.logger.isWarnEnabled()) {
                                this.logger.warn("Could not cast attribute value as a byte[]" + " or a String");
                            }
                        }
                        if (encodedAttrValue != null) {
                            entry.append(attrName).append(":: ").append(encodedAttrValue).append(LINE_SEPARATOR);
                        }
                    } else {
                        entry.append(attrName).append(": ").append(attrValue).append(LINE_SEPARATOR);
                    }
                }
            }
        }

        if (entry.length() > 0) {
            entry.append(LINE_SEPARATOR);
        }
        return entry.toString();
    }

    /**
     * This determines whether the supplied data should be base64 encoded. See
     * http://www.faqs.org/rfcs/rfc2849.html for more details.
     *
     * @param  data  <code>Object</code> to inspect
     *
     * @return  <code>boolean</code>
     */
    private boolean encodeData(final Object data) {
        boolean encode = false;
        if (data instanceof String) {
            final String stringData = (String) data;
            final char[] dataCharArray = stringData.toCharArray();
            for (int i = 0; i < dataCharArray.length; i++) {
                final int charInt = (int) dataCharArray[i];
                // check for NUL
                if (charInt == NUL_CHAR) {
                    encode = true;
                    // check for LF
                } else if (charInt == LF_CHAR) {
                    encode = true;
                    // check for CR
                } else if (charInt == CR_CHAR) {
                    encode = true;
                    // check for SP at beginning or end of string
                } else if (charInt == SP_CHAR && (i == 0 || i == dataCharArray.length - 1)) {
                    encode = true;
                    // check for colon(:) at beginning of string
                } else if (charInt == COLON_CHAR && i == 0) {
                    encode = true;
                    // check for left arrow(<) at beginning of string
                } else if (charInt == LA_CHAR && i == 0) {
                    encode = true;
                    // check for any character above 127
                } else if (charInt > MAX_ASCII_CHAR) {
                    encode = true;
                }
            }
        } else {
            encode = true;
        }
        return encode;
    }

    /**
     * This will write the supplied LDAP search results to the supplied writer in
     * LDIF form.
     *
     * @param  results  <code>Iterator</code> of LDAP search results
     * @param  writer  <code>Writer</code> to write to
     *
     * @throws  IOException  if an error occurs while writing to the output stream
     */
    public void outputLdif(final Iterator<SearchResult> results, final Writer writer) throws IOException {
        writer.write(createLdif(results));
        writer.flush();
    }

    /**
     * This will write the supplied LDAP search results to the supplied writer in
     * LDIF form.
     *
     * @param  result  <code>LdapResult</code>
     * @param  writer  <code>Writer</code> to write to
     *
     * @throws  IOException  if an error occurs while writing to the output stream
     */
    public void outputLdif(final LdapResult result, final Writer writer) throws IOException {
        writer.write(createLdif(result));
        writer.flush();
    }

    /**
     * This will take a Reader containing an LDIF and convert it to an Iterator of
     * LDAP search results. Provides a loose implementation of RFC 2849. Should
     * not be used to validate LDIF format as it does not enforce strictness.
     *
     * @param  reader  <code>Reader</code> containing LDIF content
     *
     * @return  <code>Iterator</code> - of LDAP search results
     *
     * @throws  IOException  if an I/O error occurs
     */
    public Iterator<SearchResult> importLdif(final Reader reader) throws IOException {
        return this.importLdifToLdapResult(reader).toSearchResults().iterator();
    }

    /**
     * This will take a Reader containing an LDIF and convert it to an <code>
     * LdapResult</code>. Provides a loose implementation of RFC 2849. Should not
     * be used to validate LDIF format as it does not enforce strictness.
     *
     * @param  reader  <code>Reader</code> containing LDIF content
     *
     * @return  <code>LdapResult</code> - LDAP search results
     *
     * @throws  IOException  if an I/O error occurs
     */
    public LdapResult importLdifToLdapResult(final Reader reader) throws IOException {
        final LdapResult ldapResult = this.beanFactory.newLdapResult();
        final BufferedReader br = new BufferedReader(reader);
        String line = null;
        int lineCount = 0;
        LdapEntry ldapEntry = null;
        StringBuffer lineValue = new StringBuffer();

        while ((line = br.readLine()) != null) {
            lineCount++;
            if (line.startsWith("dn:")) {
                lineValue.append(line);
                ldapEntry = this.beanFactory.newLdapEntry();
                break;
            }
        }

        boolean read = true;
        while (read) {
            line = br.readLine();
            if (line == null) {
                read = false;
                line = "";
            }
            if (!line.startsWith("#")) {
                if (line.startsWith("dn:")) {
                    ldapResult.addEntry(ldapEntry);
                    ldapEntry = this.beanFactory.newLdapEntry();
                }
                if (line.startsWith(" ")) {
                    lineValue.append(line.substring(1));
                } else {
                    final String s = lineValue.toString();
                    if (s.indexOf(":") != -1) {
                        boolean isBinary = false;
                        boolean isUrl = false;
                        final String[] parts = s.split(":", 2);
                        final String attrName = parts[0];
                        String attrValue = parts[1];
                        if (attrValue.startsWith(":")) {
                            isBinary = true;
                            attrValue = attrValue.substring(1);
                        } else if (attrValue.startsWith("<")) {
                            isUrl = true;
                            attrValue = attrValue.substring(1);
                        }
                        if (attrValue.startsWith(" ")) {
                            attrValue = attrValue.substring(1);
                        }
                        if ("dn".equals(attrName)) {
                            ldapEntry.setDn(attrValue);
                        } else {
                            LdapAttribute ldapAttr = ldapEntry.getLdapAttributes().getAttribute(attrName);
                            if (ldapAttr == null) {
                                ldapAttr = this.beanFactory.newLdapAttribute();
                                ldapAttr.setName(attrName);
                                ldapEntry.getLdapAttributes().addAttribute(ldapAttr);
                            }
                            if (isBinary) {
                                ldapAttr.getValues().add(LdapUtil.base64Decode(attrValue));
                            } else if (isUrl) {
                                ldapAttr.getValues().add(LdapUtil.readURL(new URL(attrValue)));
                            } else {
                                ldapAttr.getValues().add(attrValue);
                            }
                        }
                    }
                    lineValue = new StringBuffer(line);
                }
            }
        }
        if (ldapEntry != null) {
            ldapResult.addEntry(ldapEntry);
        }
        return ldapResult;
    }
}