/vt-ldap/branches/vt-ldap-3/src/main/java/edu/vt/middleware/ldap/ldif/Ldif.java
http://vt-middleware.googlecode.com/ · Java · 398 lines · 241 code · 39 blank · 118 comment · 81 complexity · 7a7c086d093c3a777e10477c2d054352 MD5 · raw file
- /*
- $Id: Ldif.java 1330 2010-05-23 22:10:53Z dfisher $
- Copyright (C) 2003-2010 Virginia Tech.
- All rights reserved.
- SEE LICENSE FOR MORE INFORMATION
- Author: Middleware Services
- Email: middleware@vt.edu
- Version: $Revision: 1330 $
- Updated: $Date: 2010-05-24 00:10:53 +0200 (Mon, 24 May 2010) $
- */
- 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: 1330 $ $Date: 2010-05-24 00:10:53 +0200 (Mon, 24 May 2010) $
- */
- 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;
- }
- }