
org.ldaptive.io.LdifReader Maven / Gradle / Ivy
/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.io;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import org.ldaptive.LdapAttribute;
import org.ldaptive.LdapEntry;
import org.ldaptive.LdapUtils;
import org.ldaptive.SearchResponse;
import org.ldaptive.SearchResultReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Reads an LDIF from a {@link Reader} and returns a {@link SearchResponse}. This implementation only supports entry
* records. It does not support change records or include statements.
*
* @author Middleware Services
*/
public class LdifReader implements SearchResultReader
{
/** Mark read back buffer size. */
private static final int READ_AHEAD_LIMIT = 1024;
/** Logger for this class. */
protected final Logger logger = LoggerFactory.getLogger(getClass());
/** Reader to read from. */
private final Reader ldifReader;
/**
* Creates a new ldif reader.
*
* @param reader to read LDIF from
*/
public LdifReader(final Reader reader)
{
ldifReader = reader;
}
/**
* Reads LDIF data from the reader and returns a search result.
*
* @return search result derived from the LDIF
*
* @throws IOException if an error occurs using the reader
*/
@Override
public SearchResponse read()
throws IOException
{
final SearchResponse result = new SearchResponse();
final BufferedReader br = new BufferedReader(ldifReader);
String line;
br.mark(READ_AHEAD_LIMIT);
while ((line = br.readLine()) != null) {
if (!line.isEmpty()) {
br.reset();
final List section = readSection(br);
if (!section.isEmpty()) {
if (section.get(0).startsWith("version")) {
section.remove(0);
}
if (!section.isEmpty()) {
if (section.get(0).startsWith("dn")) {
result.addEntries(parseEntry(section));
} else if (section.get(0).startsWith("ref")) {
result.addReferences(parseReference(section));
} else {
logger.debug("Unknown LDIF section {}", section.get(0));
}
}
}
}
br.mark(READ_AHEAD_LIMIT);
}
return result;
}
/**
* Reads the supplied reader line-by-line until the reader is empty or a empty line is encountered. Lines containing
* comments are ignored.
*
* @param reader to read
*
* @return list of a lines in the section
*
* @throws IOException if an error occurs reading
*/
private List readSection(final BufferedReader reader)
throws IOException
{
final List section = new ArrayList<>();
boolean readingComment = false;
String line;
while ((line = reader.readLine()) != null) {
if (line.isEmpty()) {
// end of section
break;
} else if (line.startsWith("#")) {
readingComment = true;
} else if (line.startsWith(" ")) {
if (!readingComment) {
section.add(section.remove(section.size() - 1) + line.substring(1));
}
} else {
readingComment = false;
section.add(line);
}
}
return section;
}
/**
* Parses the supplied array of LDIF lines and returns an LDAP entry.
*
* @param section of LDIF lines
*
* @return ldap entry
*
* @throws IOException if an errors occurs reading a URI in the LDIF
*/
private LdapEntry parseEntry(final List section)
throws IOException
{
final LdapEntry entry = new LdapEntry();
for (String line : section) {
if (!line.contains(":")) {
throw new IllegalArgumentException("Invalid LDAP entry data: " + line);
}
final LdapAttribute newAttr = parseAttribute(line);
if ("dn".equals(newAttr.getName())) {
entry.setDn(newAttr.getStringValue());
} else {
entry.mergeAttributes(newAttr);
}
}
return entry;
}
/**
* Parses the supplied line and returns an attribute with a single value found in the line.
*
* @param line to parse
*
* @return ldap attribute
*
* @throws IOException if an errors occurs reading a URI in the LDIF
*/
private LdapAttribute parseAttribute(final String line)
throws IOException
{
boolean isBase64 = false;
boolean isUrl = false;
final String[] parts = line.split(":", 2);
final String attrName = parts[0];
String attrValue = parts[1];
if (attrValue.startsWith(":")) {
isBase64 = true;
attrValue = attrValue.substring(1);
} else if (attrValue.startsWith("<")) {
isUrl = true;
attrValue = attrValue.substring(1);
}
// remove leading whitespace
while (attrValue.startsWith(" ")) {
attrValue = attrValue.substring(1);
}
final LdapAttribute attr = new LdapAttribute(attrName);
if (isBase64) {
attr.addBinaryValues(LdapUtils.base64Decode(attrValue));
} else if (isUrl) {
final byte[] b;
if (ResourceUtils.isResource(attrValue)) {
b = ResourceUtils.readResource(attrValue);
} else {
b = ResourceUtils.readResource(attrValue, new URLResourceLoader());
}
attr.addBinaryValues(b);
} else {
attr.addStringValues(attrValue);
}
return attr;
}
/**
* Parses the supplied array of LDIF lines and returns a search reference.
*
* @param section of LDIF lines
*
* @return search reference
*/
private SearchResultReference parseReference(final List section)
{
final SearchResultReference ref = new SearchResultReference();
for (String line : section) {
if (!line.contains(":")) {
throw new IllegalArgumentException("Invalid LDAP reference data: " + line);
}
final String[] parts = line.split(":", 2);
if (!"ref".equals(parts[0])) {
throw new IllegalArgumentException("Invalid LDAP reference data: " + line);
}
if (parts[1].startsWith(" ")) {
ref.addUris(parts[1].substring(1));
} else if (!parts[1].isEmpty()) {
throw new IllegalArgumentException("Invalid LDAP reference data: " + line);
}
}
return ref;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy