| | |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | package org.opends.sdk.ldif; |
| | | |
| | | |
| | | |
| | | import static com.sun.opends.sdk.messages.Messages. |
| | | WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND; |
| | | import static com.sun.opends.sdk.messages.Messages. |
| | | WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND; |
| | | import static com.sun.opends.sdk.messages.Messages. |
| | | WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR; |
| | | import static com.sun.opends.sdk.messages.Messages.*; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.NoSuchElementException; |
| | | |
| | | import org.opends.sdk.*; |
| | | import org.opends.sdk.schema.Schema; |
| | |
| | | public final class LDIFEntryReader extends AbstractLDIFReader implements |
| | | EntryReader |
| | | { |
| | | // Poison used to indicate end of LDIF. |
| | | private static final Entry EOF = new LinkedHashMapEntry(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Parses the provided array of LDIF lines as a single LDIF entry. |
| | | * |
| | |
| | | final LDIFEntryReader reader = new LDIFEntryReader(ldifLines); |
| | | try |
| | | { |
| | | final Entry entry = reader.readEntry(); |
| | | |
| | | if (entry == null) |
| | | if (!reader.hasNext()) |
| | | { |
| | | // No change record found. |
| | | final LocalizableMessage message = WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND |
| | |
| | | throw new LocalizedIllegalArgumentException(message); |
| | | } |
| | | |
| | | if (reader.readEntry() != null) |
| | | final Entry entry = reader.readEntry(); |
| | | |
| | | if (reader.hasNext()) |
| | | { |
| | | // Multiple change records found. |
| | | final LocalizableMessage message = WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND |
| | |
| | | |
| | | |
| | | |
| | | private Entry nextEntry = null; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new LDIF entry reader whose source is the provided input stream. |
| | | * |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void close() throws IOException |
| | | { |
| | | close0(); |
| | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * |
| | | * @throws DecodeException |
| | | * If the entry could not be decoded because it was malformed. |
| | | */ |
| | | @Override |
| | | public boolean hasNext() throws DecodeException, IOException |
| | | { |
| | | return getNextEntry() != EOF; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * |
| | | * @throws DecodeException |
| | | * If the entry could not be decoded because it was malformed. |
| | | */ |
| | | @Override |
| | | public Entry readEntry() throws DecodeException, IOException |
| | | { |
| | | // Continue until an unfiltered entry is obtained. |
| | | while (true) |
| | | if (!hasNext()) |
| | | { |
| | | LDIFRecord record = null; |
| | | |
| | | // Read the set of lines that make up the next entry. |
| | | record = readLDIFRecord(); |
| | | if (record == null) |
| | | { |
| | | return null; |
| | | } |
| | | |
| | | // Read the DN of the entry and see if it is one that should be |
| | | // included in the import. |
| | | DN entryDN; |
| | | try |
| | | { |
| | | entryDN = readLDIFRecordDN(record); |
| | | if (entryDN == null) |
| | | { |
| | | // Skip version record. |
| | | continue; |
| | | } |
| | | } |
| | | catch (final DecodeException e) |
| | | { |
| | | rejectLDIFRecord(record, e.getMessageObject()); |
| | | continue; |
| | | } |
| | | |
| | | // Skip if branch containing the entry DN is excluded. |
| | | if (isBranchExcluded(entryDN)) |
| | | { |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Skipping entry because it is in excluded branch"); |
| | | skipLDIFRecord(record, message); |
| | | continue; |
| | | } |
| | | |
| | | // Use an Entry for the AttributeSequence. |
| | | final Entry entry = new LinkedHashMapEntry(entryDN); |
| | | try |
| | | { |
| | | while (record.iterator.hasNext()) |
| | | { |
| | | final String ldifLine = record.iterator.next(); |
| | | readLDIFRecordAttributeValue(record, ldifLine, entry); |
| | | } |
| | | } |
| | | catch (final DecodeException e) |
| | | { |
| | | rejectLDIFRecord(record, e.getMessageObject()); |
| | | continue; |
| | | } |
| | | |
| | | // Skip if the entry is excluded by any filters. |
| | | if (isEntryExcluded(entry)) |
| | | { |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Skipping entry due to exclusing filters"); |
| | | skipLDIFRecord(record, message); |
| | | continue; |
| | | } |
| | | |
| | | return entry; |
| | | // LDIF reader has completed successfully. |
| | | throw new NoSuchElementException(); |
| | | } |
| | | |
| | | final Entry entry = nextEntry; |
| | | nextEntry = null; |
| | | return entry; |
| | | } |
| | | |
| | | |
| | |
| | | * entries that are read from LDIF. The default is {@code false}. |
| | | * |
| | | * @param excludeUserAttributes |
| | | * {@code true} if all user attributes should be excluded, or {@code |
| | | * false} otherwise. |
| | | * {@code true} if all user attributes should be excluded, or |
| | | * {@code false} otherwise. |
| | | * @return A reference to this {@code LDIFEntryReader}. |
| | | */ |
| | | public LDIFEntryReader setExcludeAllUserAttributes( |
| | |
| | | * that are read from LDIF. The default is {@code true}. |
| | | * |
| | | * @param validateSchema |
| | | * {@code true} if schema validation should be performed, or {@code |
| | | * false} otherwise. |
| | | * {@code true} if schema validation should be performed, or |
| | | * {@code false} otherwise. |
| | | * @return A reference to this {@code LDIFEntryReader}. |
| | | */ |
| | | public LDIFEntryReader setValidateSchema(final boolean validateSchema) |
| | |
| | | return this; |
| | | } |
| | | |
| | | |
| | | |
| | | private Entry getNextEntry() throws DecodeException, IOException |
| | | { |
| | | while (nextEntry == null) |
| | | { |
| | | LDIFRecord record = null; |
| | | |
| | | // Read the set of lines that make up the next entry. |
| | | record = readLDIFRecord(); |
| | | if (record == null) |
| | | { |
| | | nextEntry = EOF; |
| | | break; |
| | | } |
| | | |
| | | // Read the DN of the entry and see if it is one that should be |
| | | // included in the import. |
| | | DN entryDN; |
| | | try |
| | | { |
| | | entryDN = readLDIFRecordDN(record); |
| | | if (entryDN == null) |
| | | { |
| | | // Skip version record. |
| | | continue; |
| | | } |
| | | } |
| | | catch (final DecodeException e) |
| | | { |
| | | rejectLDIFRecord(record, e.getMessageObject()); |
| | | continue; |
| | | } |
| | | |
| | | // Skip if branch containing the entry DN is excluded. |
| | | if (isBranchExcluded(entryDN)) |
| | | { |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Skipping entry because it is in excluded branch"); |
| | | skipLDIFRecord(record, message); |
| | | continue; |
| | | } |
| | | |
| | | // Use an Entry for the AttributeSequence. |
| | | final Entry entry = new LinkedHashMapEntry(entryDN); |
| | | try |
| | | { |
| | | while (record.iterator.hasNext()) |
| | | { |
| | | final String ldifLine = record.iterator.next(); |
| | | readLDIFRecordAttributeValue(record, ldifLine, entry); |
| | | } |
| | | } |
| | | catch (final DecodeException e) |
| | | { |
| | | rejectLDIFRecord(record, e.getMessageObject()); |
| | | continue; |
| | | } |
| | | |
| | | // Skip if the entry is excluded by any filters. |
| | | if (isEntryExcluded(entry)) |
| | | { |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Skipping entry due to exclusing filters"); |
| | | skipLDIFRecord(record, message); |
| | | continue; |
| | | } |
| | | |
| | | nextEntry = entry; |
| | | } |
| | | |
| | | return nextEntry; |
| | | } |
| | | |
| | | } |