Partial fix for OPENDJ-205: Add support for rejecting and skipping records to the LDIF readers
Added new interface RejectedRecordListener which can be configured for LDIFEntryReader and LDIFChangeRecordReaders.
Renamed Schema.nonStrict() -> Schema.asNonStrictSchema() and added Schema.asStrictSchema().
Fixed all usages of raw messages if LDIF package.
2 files added
14 files modified
| | |
| | | * @param attributeDescription |
| | | * The LDAP string representation of an attribute description. |
| | | * @return The parsed attribute description. |
| | | * @throws UnknownSchemaElementException |
| | | * If {@code attributeDescription} contains an attribute type which |
| | | * is not contained in the default schema and the schema is strict. |
| | | * @throws LocalizedIllegalArgumentException |
| | | * If {@code attributeDescription} is not a valid LDAP string |
| | | * representation of an attribute description. |
| | |
| | | * If {@code attributeDescription} was {@code null}. |
| | | */ |
| | | public static AttributeDescription valueOf(final String attributeDescription) |
| | | throws LocalizedIllegalArgumentException, NullPointerException |
| | | throws UnknownSchemaElementException, LocalizedIllegalArgumentException, |
| | | NullPointerException |
| | | { |
| | | return valueOf(attributeDescription, Schema.getDefaultSchema()); |
| | | } |
| | |
| | | * @param schema |
| | | * The schema to use when parsing the attribute description. |
| | | * @return The parsed attribute description. |
| | | * @throws UnknownSchemaElementException |
| | | * If {@code attributeDescription} contains an attribute type which |
| | | * is not contained in the provided schema and the schema is strict. |
| | | * @throws LocalizedIllegalArgumentException |
| | | * If {@code attributeDescription} is not a valid LDAP string |
| | | * representation of an attribute description. |
| | | * @throws NullPointerException |
| | | * If {@code attributeDescription} or {@code schema} was {@code |
| | | * null}. |
| | | * If {@code attributeDescription} or {@code schema} was |
| | | * {@code null}. |
| | | */ |
| | | @SuppressWarnings("serial") |
| | | public static AttributeDescription valueOf(final String attributeDescription, |
| | | final Schema schema) throws LocalizedIllegalArgumentException, |
| | | NullPointerException |
| | | final Schema schema) throws UnknownSchemaElementException, |
| | | LocalizedIllegalArgumentException, NullPointerException |
| | | { |
| | | Validator.ensureNotNull(attributeDescription, schema); |
| | | |
| | |
| | | } |
| | | |
| | | // Get the attribute type from the schema. |
| | | final AttributeType attributeType; |
| | | try |
| | | { |
| | | attributeType = schema.getAttributeType(oid); |
| | | } |
| | | catch (final UnknownSchemaElementException e) |
| | | { |
| | | final LocalizableMessage message = ERR_ATTRIBUTE_DESCRIPTION_TYPE_NOT_FOUND |
| | | .get(attributeDescription, e.getMessageObject()); |
| | | throw new LocalizedIllegalArgumentException(message); |
| | | } |
| | | final AttributeType attributeType = schema.getAttributeType(oid); |
| | | |
| | | // If we're already at the end of the attribute description then it |
| | | // does not contain any options. |
| | |
| | | addRFC3112(builder); |
| | | addSunProprietary(builder); |
| | | |
| | | SINGLETON = builder.toSchema().nonStrict(); |
| | | SINGLETON = builder.toSchema().asNonStrictSchema(); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | try |
| | | { |
| | | DN dn = DN.valueOf(value.toString(), schema.nonStrict()); |
| | | DN dn = DN.valueOf(value.toString(), schema.asNonStrictSchema()); |
| | | StringBuilder builder = new StringBuilder(value.length()); |
| | | return ByteString.valueOf(normalizeDN(builder, dn)); |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether or not this schema is strict. Attribute type queries in |
| | | * non-strict schema always succeed: if the requested attribute type is not |
| | | * found then a temporary attribute type is created automatically having the |
| | | * Octet String syntax and associated matching rules. Strict schema, on the |
| | | * other hand, throw an {@link UnknownSchemaElementException} whenever an |
| | | * attempt is made to retrieve a non-existent attribute type. |
| | | * Indicates whether or not this schema is strict. |
| | | * <p> |
| | | * Attribute type queries against non-strict schema always succeed: if the |
| | | * requested attribute type is not found then a temporary attribute type is |
| | | * created automatically having the Octet String syntax and associated |
| | | * matching rules. |
| | | * <p> |
| | | * Strict schema, on the other hand, throw an |
| | | * {@link UnknownSchemaElementException} whenever an attempt is made to |
| | | * retrieve a non-existent attribute type. |
| | | * |
| | | * @return {@code true} if this schema is strict. |
| | | */ |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns a non-strict view of this schema. Attribute type queries in |
| | | * non-strict schema always succeed: if the requested attribute type is not |
| | | * found then a temporary attribute type is created automatically having the |
| | | * Octet String syntax and associated matching rules. Strict schema, on the |
| | | * other hand, throw an {@link UnknownSchemaElementException} whenever an |
| | | * attempt is made to retrieve a non-existent attribute type. |
| | | * Returns a non-strict view of this schema. |
| | | * <p> |
| | | * See the description of {@link #isStrict()} for more details. |
| | | * |
| | | * @return A non-strict view of this schema. |
| | | * @see Schema#isStrict() |
| | | */ |
| | | public Schema nonStrict() |
| | | public Schema asNonStrictSchema() |
| | | { |
| | | if (impl.isStrict()) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Returns a strict view of this schema. |
| | | * <p> |
| | | * See the description of {@link #isStrict()} for more details. |
| | | * |
| | | * @return A strict view of this schema. |
| | | * @see Schema#isStrict() |
| | | */ |
| | | public Schema asStrictSchema() |
| | | { |
| | | if (impl.isStrict()) |
| | | { |
| | | return this; |
| | | } |
| | | else |
| | | { |
| | | return new Schema(((NonStrictImpl) impl).strictImpl); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds the definitions of all the schema elements contained in this schema to |
| | | * the provided subschema subentry. Any existing attributes (including schema |
| | | * definitions) contained in the provided entry will be preserved. |
| | |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | import org.forgerock.i18n.LocalizedIllegalArgumentException; |
| | | import org.forgerock.opendj.ldap.*; |
| | | import org.forgerock.opendj.ldap.schema.Schema; |
| | | import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException; |
| | | |
| | | import com.forgerock.opendj.util.Base64; |
| | | import com.forgerock.opendj.util.Validator; |
| | |
| | | |
| | | |
| | | /** |
| | | *{@inheritDoc} |
| | | * {@inheritDoc} |
| | | */ |
| | | public String readLine() throws IOException |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | *{@inheritDoc} |
| | | * {@inheritDoc} |
| | | */ |
| | | public String readLine() throws IOException |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | boolean validateSchema = true; |
| | | RejectedRecordListener rejectedRecordListener = RejectedRecordListener.FAIL_FAST; |
| | | |
| | | Schema schema = Schema.getDefaultSchema().asNonStrictSchema(); |
| | | |
| | | boolean validateSchema = false; |
| | | |
| | | private final LDIFReaderImpl impl; |
| | | |
| | |
| | | { |
| | | // The value did not have a valid base64-encoding. |
| | | final LocalizableMessage message = ERR_LDIF_COULD_NOT_BASE64_DECODE_ATTR |
| | | .get(entryDN.toString(), record.lineNumber, ldifLine, e |
| | | .getMessageObject()); |
| | | .get(entryDN.toString(), record.lineNumber, ldifLine, |
| | | e.getMessageObject()); |
| | | throw DecodeException.error(message); |
| | | } |
| | | } |
| | |
| | | catch (final Exception e) |
| | | { |
| | | // The URL was malformed or had an invalid protocol. |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_URL.get(entryDN |
| | | .toString(), record.lineNumber, attrName, String.valueOf(e)); |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_URL.get( |
| | | entryDN.toString(), record.lineNumber, attrName, |
| | | String.valueOf(e)); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | |
| | | { |
| | | // We were unable to read the contents of that URL for some |
| | | // reason. |
| | | final LocalizableMessage message = ERR_LDIF_URL_IO_ERROR.get(entryDN |
| | | .toString(), record.lineNumber, attrName, String |
| | | .valueOf(contentURL), String.valueOf(e)); |
| | | final LocalizableMessage message = ERR_LDIF_URL_IO_ERROR.get( |
| | | entryDN.toString(), record.lineNumber, attrName, |
| | | String.valueOf(contentURL), String.valueOf(e)); |
| | | throw DecodeException.error(message); |
| | | } |
| | | finally |
| | |
| | | |
| | | |
| | | final void readLDIFRecordAttributeValue(final LDIFRecord record, |
| | | final String ldifLine, final Entry entry) throws DecodeException |
| | | final String ldifLine, final Entry entry, |
| | | final List<LocalizableMessage> schemaErrors) throws DecodeException |
| | | { |
| | | // Parse the attribute description. |
| | | final int colonPos = parseColonPosition(record, ldifLine); |
| | |
| | | { |
| | | attributeDescription = AttributeDescription.valueOf(attrDescr, schema); |
| | | } |
| | | catch (final UnknownSchemaElementException e) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_UNKNOWN_ATTRIBUTE_TYPE.get( |
| | | record.lineNumber, entry.getName().toString(), attrDescr); |
| | | if (validateSchema) |
| | | { |
| | | schemaErrors.add(message); |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | throw DecodeException.error(message); |
| | | } |
| | | } |
| | | catch (final LocalizedIllegalArgumentException e) |
| | | { |
| | | throw DecodeException.error(e.getMessageObject()); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_ATTRIBUTE_NAME.get( |
| | | record.lineNumber, entry.getName().toString(), attrDescr); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | // Now parse the attribute value. |
| | |
| | | { |
| | | if (validateSchema && attributeDescription.containsOption("binary")) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_ATTR_OPTION.get( |
| | | entry.getName().toString(), record.lineNumber, attrDescr); |
| | | throw DecodeException.error(message); |
| | | final LocalizableMessage message = ERR_LDIF_UNEXPECTED_BINARY_OPTION |
| | | .get(record.lineNumber, entry.getName().toString(), attrDescr); |
| | | schemaErrors.add(message); |
| | | return; |
| | | } |
| | | } |
| | | else |
| | |
| | | if (!attributeDescription.getAttributeType().getSyntax() |
| | | .valueIsAcceptable(value, invalidReason)) |
| | | { |
| | | final LocalizableMessage message = WARN_LDIF_VALUE_VIOLATES_SYNTAX |
| | | .get(entry.getName().toString(), record.lineNumber, value |
| | | .toString(), attrDescr, invalidReason); |
| | | throw DecodeException.error(message); |
| | | final LocalizableMessage message = WARN_LDIF_MALFORMED_ATTRIBUTE_VALUE |
| | | .get(record.lineNumber, entry.getName().toString(), |
| | | value.toString(), attrDescr, invalidReason); |
| | | schemaErrors.add(message); |
| | | return; |
| | | } |
| | | } |
| | | |
| | |
| | | if (!attributeDescription.getAttributeType().getSyntax() |
| | | .valueIsAcceptable(value, invalidReason)) |
| | | { |
| | | final LocalizableMessage message = WARN_LDIF_VALUE_VIOLATES_SYNTAX |
| | | .get(entry.getName().toString(), record.lineNumber, value |
| | | .toString(), attrDescr, invalidReason); |
| | | throw DecodeException.error(message); |
| | | final LocalizableMessage message = WARN_LDIF_MALFORMED_ATTRIBUTE_VALUE |
| | | .get(record.lineNumber, entry.getName().toString(), |
| | | value.toString(), attrDescr, invalidReason); |
| | | schemaErrors.add(message); |
| | | return; |
| | | } |
| | | |
| | | if (!attribute.add(value)) |
| | | if (!attribute.add(value) && validateSchema) |
| | | { |
| | | final LocalizableMessage message = WARN_LDIF_DUPLICATE_ATTR.get(entry |
| | | .getName().toString(), record.lineNumber, attrDescr, value |
| | | .toString()); |
| | | throw DecodeException.error(message); |
| | | final LocalizableMessage message = WARN_LDIF_DUPLICATE_ATTRIBUTE_VALUE |
| | | .get(record.lineNumber, entry.getName().toString(), attrDescr, |
| | | value.toString()); |
| | | schemaErrors.add(message); |
| | | return; |
| | | } |
| | | |
| | | if (attributeDescription.getAttributeType().isSingleValue()) |
| | | if (validateSchema |
| | | && attributeDescription.getAttributeType().isSingleValue()) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_MULTIPLE_VALUES_FOR_SINGLE_VALUED_ATTR |
| | | .get(entry.getName().toString(), record.lineNumber, attrDescr); |
| | | throw DecodeException.error(message); |
| | | final LocalizableMessage message = ERR_LDIF_MULTI_VALUED_SINGLE_VALUED_ATTRIBUTE |
| | | .get(record.lineNumber, entry.getName().toString(), attrDescr); |
| | | schemaErrors.add(message); |
| | | return; |
| | | } |
| | | } |
| | | else |
| | |
| | | |
| | | final String readLDIFRecordKeyValuePair(final LDIFRecord record, |
| | | final KeyValuePair pair, final boolean allowBase64) |
| | | throws DecodeException |
| | | { |
| | | final String ldifLine = record.iterator.next(); |
| | | final int colonPos = ldifLine.indexOf(":"); |
| | | if (colonPos <= 0) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_NO_ATTR_NAME.get( |
| | | record.lineNumber, ldifLine); |
| | | throw DecodeException.error(message); |
| | | pair.key = null; |
| | | return ldifLine; |
| | | } |
| | | pair.key = ldifLine.substring(0, colonPos); |
| | | |
| | |
| | | final int length = ldifLine.length(); |
| | | if (colonPos == length - 1) |
| | | { |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Malformed changetype attribute"); |
| | | throw DecodeException.error(message); |
| | | pair.key = null; |
| | | return ldifLine; |
| | | } |
| | | |
| | | if (allowBase64 && ldifLine.charAt(colonPos + 1) == ':') |
| | |
| | | } |
| | | catch (final LocalizedIllegalArgumentException e) |
| | | { |
| | | // The value did not have a valid base64-encoding. |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Malformed base64 changetype attribute"); |
| | | throw DecodeException.error(message); |
| | | pair.key = null; |
| | | return ldifLine; |
| | | } |
| | | } |
| | | else |
| | |
| | | |
| | | |
| | | |
| | | final void rejectLDIFRecord(final LDIFRecord record, |
| | | final void handleMalformedRecord(final LDIFRecord record, |
| | | final LocalizableMessage message) throws DecodeException |
| | | { |
| | | // FIXME: not yet implemented. |
| | | throw DecodeException.error(message); |
| | | rejectedRecordListener.handleMalformedRecord(record.lineNumber, |
| | | record.ldifLines, message); |
| | | } |
| | | |
| | | |
| | | |
| | | final void skipLDIFRecord(final LDIFRecord record, |
| | | final LocalizableMessage message) |
| | | final void handleSchemaValidationFailure(final LDIFRecord record, |
| | | final List<LocalizableMessage> messages) throws DecodeException |
| | | { |
| | | // FIXME: not yet implemented. |
| | | rejectedRecordListener.handleSchemaValidationFailure(record.lineNumber, |
| | | record.ldifLines, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | final void handleSkippedRecord(final LDIFRecord record, |
| | | final LocalizableMessage message) throws DecodeException |
| | | { |
| | | rejectedRecordListener.handleSkippedRecord(record.lineNumber, |
| | | record.ldifLines, message); |
| | | } |
| | | |
| | | |
| | |
| | | * |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | * Portions copyright 2011 ForgeRock AS |
| | | */ |
| | | |
| | | package org.forgerock.opendj.ldif; |
| | |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.forgerock.opendj.ldap.Matcher; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.forgerock.opendj.ldap.schema.Schema; |
| | | |
| | | |
| | | |
| | |
| | | |
| | | final Set<AttributeDescription> includeAttributes = new HashSet<AttributeDescription>(); |
| | | |
| | | Schema schema = Schema.getDefaultSchema(); |
| | | |
| | | final Set<DN> includeBranches = new HashSet<DN>(); |
| | | |
| | | final Set<DN> excludeBranches = new HashSet<DN>(); |
| | |
| | | * |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | * Portions copyright 2011 ForgeRock AS |
| | | */ |
| | | |
| | | package org.forgerock.opendj.ldif; |
| | |
| | | import org.forgerock.opendj.ldap.ByteSequence; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.schema.Schema; |
| | | |
| | | import com.forgerock.opendj.util.Base64; |
| | | import com.forgerock.opendj.util.Validator; |
| | |
| | | |
| | | private final StringBuilder builder = new StringBuilder(80); |
| | | |
| | | Schema schema = Schema.getDefaultSchema(); |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | /** |
| | | * An interface for writing change records to a data source, typically an LDIF |
| | | * file. |
| | | * <p> |
| | | * TODO: FilteredChangeRecordWriter |
| | | */ |
| | | public interface ChangeRecordWriter extends Closeable, Flushable |
| | | { |
| | |
| | | |
| | | /** |
| | | * An interface for writing entries to a data source, typically an LDIF file. |
| | | * <p> |
| | | * TODO: FilteredChangeRecordWriter |
| | | */ |
| | | public interface EntryWriter extends Closeable, Flushable |
| | | { |
| | |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.NoSuchElementException; |
| | | import java.util.*; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizedIllegalArgumentException; |
| | |
| | | import org.forgerock.opendj.ldap.requests.ModifyRequest; |
| | | import org.forgerock.opendj.ldap.requests.Requests; |
| | | import org.forgerock.opendj.ldap.schema.Schema; |
| | | import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException; |
| | | |
| | | import com.forgerock.opendj.util.Validator; |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Sets the rejected record listener which should be notified whenever a |
| | | * record is skipped, malformed, or fails schema validation. |
| | | * <p> |
| | | * By default the {@link RejectedRecordListener#FAIL_FAST} listener is used. |
| | | * |
| | | * @param listener |
| | | * The rejected record listener. |
| | | * @return A reference to this {@code LDIFChangeRecordReader}. |
| | | */ |
| | | public LDIFChangeRecordReader setRejectedRecordListener( |
| | | final RejectedRecordListener listener) |
| | | { |
| | | this.rejectedRecordListener = listener; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets the schema which should be used for decoding change records that are |
| | | * read from LDIF. The default schema is used if no other is specified. |
| | | * |
| | |
| | | public LDIFChangeRecordReader setSchema(final Schema schema) |
| | | { |
| | | Validator.ensureNotNull(schema); |
| | | this.schema = schema; |
| | | this.schema = validateSchema ? schema.asStrictSchema() : schema |
| | | .asNonStrictSchema(); |
| | | return this; |
| | | } |
| | | |
| | |
| | | |
| | | /** |
| | | * Specifies whether or not schema validation should be performed for change |
| | | * records that are read from LDIF. The default is {@code true} . |
| | | * records that are read from LDIF. |
| | | * <p> |
| | | * When enabled, the LDIF reader will implicitly use a strict schema so that |
| | | * unrecognized attribute types will be detected. |
| | | * <p> |
| | | * Schema validation is disabled by default. |
| | | * |
| | | * @param validateSchema |
| | | * {@code true} if schema validation should be performed, or |
| | |
| | | public LDIFChangeRecordReader setValidateSchema(final boolean validateSchema) |
| | | { |
| | | this.validateSchema = validateSchema; |
| | | this.schema = validateSchema ? schema.asStrictSchema() : schema |
| | | .asNonStrictSchema(); |
| | | return this; |
| | | } |
| | | |
| | |
| | | { |
| | | while (nextChangeRecord == null) |
| | | { |
| | | LDIFRecord record = null; |
| | | |
| | | // Read the set of lines that make up the next entry. |
| | | record = readLDIFRecord(); |
| | | final LDIFRecord record = readLDIFRecord(); |
| | | if (record == null) |
| | | { |
| | | nextChangeRecord = 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); |
| | | // Read the DN of the entry and see if it is one that should be |
| | | // included in the import. |
| | | final DN 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; |
| | | } |
| | | // Skip if branch containing the entry DN is excluded. |
| | | if (isBranchExcluded(entryDN)) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_CHANGE_EXCLUDED_BY_DN |
| | | .get(record.lineNumber, entryDN.toString()); |
| | | handleSkippedRecord(record, message); |
| | | continue; |
| | | } |
| | | |
| | | ChangeRecord changeRecord = null; |
| | | try |
| | | { |
| | | if (!record.iterator.hasNext()) |
| | | { |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Missing changetype"); |
| | | final LocalizableMessage message = ERR_LDIF_NO_CHANGE_TYPE.get( |
| | | record.lineNumber, entryDN.toString()); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | final KeyValuePair pair = new KeyValuePair(); |
| | | final String ldifLine = readLDIFRecordKeyValuePair(record, pair, false); |
| | | if (pair.key == null) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_CHANGE_TYPE |
| | | .get(record.lineNumber, entryDN.toString(), ldifLine); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | if (!toLowerCase(pair.key).equals("changetype")) |
| | | { |
| | | // Default to add change record. |
| | | changeRecord = parseAddChangeRecordEntry(entryDN, ldifLine, record); |
| | | nextChangeRecord = parseAddChangeRecordEntry(entryDN, ldifLine, |
| | | record); |
| | | } |
| | | else |
| | | { |
| | | final String changeType = toLowerCase(pair.value); |
| | | if (changeType.equals("add")) |
| | | { |
| | | changeRecord = parseAddChangeRecordEntry(entryDN, null, record); |
| | | nextChangeRecord = parseAddChangeRecordEntry(entryDN, null, record); |
| | | } |
| | | else if (changeType.equals("delete")) |
| | | { |
| | | changeRecord = parseDeleteChangeRecordEntry(entryDN, record); |
| | | nextChangeRecord = parseDeleteChangeRecordEntry(entryDN, record); |
| | | } |
| | | else if (changeType.equals("modify")) |
| | | { |
| | | changeRecord = parseModifyChangeRecordEntry(entryDN, record); |
| | | nextChangeRecord = parseModifyChangeRecordEntry(entryDN, record); |
| | | } |
| | | else if (changeType.equals("modrdn")) |
| | | { |
| | | changeRecord = parseModifyDNChangeRecordEntry(entryDN, record); |
| | | nextChangeRecord = parseModifyDNChangeRecordEntry(entryDN, record); |
| | | } |
| | | else if (changeType.equals("moddn")) |
| | | { |
| | | changeRecord = parseModifyDNChangeRecordEntry(entryDN, record); |
| | | nextChangeRecord = parseModifyDNChangeRecordEntry(entryDN, record); |
| | | } |
| | | else |
| | | { |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_CHANGETYPE_ATTRIBUTE |
| | | .get(pair.value, "add, delete, modify, moddn, modrdn"); |
| | | final LocalizableMessage message = ERR_LDIF_BAD_CHANGE_TYPE.get( |
| | | record.lineNumber, entryDN.toString(), pair.value); |
| | | throw DecodeException.error(message); |
| | | } |
| | | } |
| | | } |
| | | catch (final DecodeException e) |
| | | { |
| | | rejectLDIFRecord(record, e.getMessageObject()); |
| | | handleMalformedRecord(record, e.getMessageObject()); |
| | | continue; |
| | | } |
| | | |
| | | if (changeRecord != null) |
| | | { |
| | | nextChangeRecord = changeRecord; |
| | | } |
| | | } |
| | | return nextChangeRecord; |
| | | } |
| | |
| | | { |
| | | // Use an Entry for the AttributeSequence. |
| | | final Entry entry = new LinkedHashMapEntry(entryDN); |
| | | final List<LocalizableMessage> schemaErrors = new LinkedList<LocalizableMessage>(); |
| | | |
| | | if (lastLDIFLine != null) |
| | | { |
| | | // This line was read when looking for the change type. |
| | | readLDIFRecordAttributeValue(record, lastLDIFLine, entry); |
| | | readLDIFRecordAttributeValue(record, lastLDIFLine, entry, schemaErrors); |
| | | } |
| | | |
| | | while (record.iterator.hasNext()) |
| | | { |
| | | final String ldifLine = record.iterator.next(); |
| | | readLDIFRecordAttributeValue(record, ldifLine, entry); |
| | | readLDIFRecordAttributeValue(record, ldifLine, entry, schemaErrors); |
| | | } |
| | | |
| | | if (!schemaErrors.isEmpty()) |
| | | { |
| | | handleSchemaValidationFailure(record, schemaErrors); |
| | | return null; |
| | | } |
| | | |
| | | return Requests.newAddRequest(entry); |
| | |
| | | { |
| | | if (record.iterator.hasNext()) |
| | | { |
| | | // FIXME: include line number in error. |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_DELETE_ATTRIBUTES |
| | | .get(); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_DELETE.get( |
| | | record.lineNumber, entryDN.toString()); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | |
| | | |
| | | final KeyValuePair pair = new KeyValuePair(); |
| | | final List<ByteString> attributeValues = new ArrayList<ByteString>(); |
| | | final List<LocalizableMessage> schemaErrors = new LinkedList<LocalizableMessage>(); |
| | | |
| | | while (record.iterator.hasNext()) |
| | | { |
| | | readLDIFRecordKeyValuePair(record, pair, false); |
| | | String ldifLine = readLDIFRecordKeyValuePair(record, pair, false); |
| | | if (pair.key == null) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_MODIFICATION_TYPE |
| | | .get(record.lineNumber, entryDN.toString(), ldifLine); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | final String changeType = toLowerCase(pair.key); |
| | | |
| | | ModificationType modType; |
| | |
| | | } |
| | | else |
| | | { |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_MODIFY_ATTRIBUTE |
| | | .get(pair.key, "add, delete, replace, increment"); |
| | | final LocalizableMessage message = ERR_LDIF_BAD_MODIFICATION_TYPE.get( |
| | | record.lineNumber, entryDN.toString(), pair.key); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | |
| | | { |
| | | attributeDescription = AttributeDescription.valueOf(pair.value, schema); |
| | | } |
| | | catch (final UnknownSchemaElementException e) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_UNKNOWN_ATTRIBUTE_TYPE.get( |
| | | record.lineNumber, entryDN.toString(), pair.value); |
| | | if (validateSchema) |
| | | { |
| | | schemaErrors.add(message); |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | throw DecodeException.error(message); |
| | | } |
| | | } |
| | | catch (final LocalizedIllegalArgumentException e) |
| | | { |
| | | throw DecodeException.error(e.getMessageObject()); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_ATTRIBUTE_NAME |
| | | .get(record.lineNumber, entryDN.toString(), pair.value); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | // Skip the attribute if requested before performing any schema |
| | |
| | | { |
| | | if (validateSchema && attributeDescription.containsOption("binary")) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_ATTR_OPTION.get( |
| | | entryDN.toString(), record.lineNumber, pair.value); |
| | | throw DecodeException.error(message); |
| | | final LocalizableMessage message = ERR_LDIF_UNEXPECTED_BINARY_OPTION |
| | | .get(record.lineNumber, entryDN.toString(), pair.value); |
| | | schemaErrors.add(message); |
| | | continue; |
| | | } |
| | | } |
| | | else |
| | |
| | | attributeValues.clear(); |
| | | while (record.iterator.hasNext()) |
| | | { |
| | | final String ldifLine = record.iterator.next(); |
| | | ldifLine = record.iterator.next(); |
| | | if (ldifLine.equals("-")) |
| | | { |
| | | break; |
| | |
| | | } |
| | | catch (final LocalizedIllegalArgumentException e) |
| | | { |
| | | throw DecodeException.error(e.getMessageObject()); |
| | | // No need to catch schema exception here because it implies that the |
| | | // attribute name is wrong. |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_ATTRIBUTE_NAME |
| | | .get(record.lineNumber, entryDN.toString(), attrDescr); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | // Ensure that the binary option is present if required. |
| | |
| | | |
| | | if (!attributeDescription2.equals(attributeDescription)) |
| | | { |
| | | // TODO: include line number. |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_CHANGERECORD_ATTRIBUTE |
| | | .get(attributeDescription2.toString(), |
| | | final LocalizableMessage message = ERR_LDIF_ATTRIBUTE_NAME_MISMATCH |
| | | .get(record.lineNumber, entryDN.toString(), |
| | | attributeDescription2.toString(), |
| | | attributeDescription.toString()); |
| | | throw DecodeException.error(message); |
| | | } |
| | |
| | | modifyRequest.addModification(change); |
| | | } |
| | | |
| | | if (!schemaErrors.isEmpty()) |
| | | { |
| | | handleSchemaValidationFailure(record, schemaErrors); |
| | | return null; |
| | | } |
| | | |
| | | return modifyRequest; |
| | | } |
| | | |
| | |
| | | // Parse the newrdn. |
| | | if (!record.iterator.hasNext()) |
| | | { |
| | | // TODO: include line number. |
| | | final LocalizableMessage message = ERR_LDIF_NO_MOD_DN_ATTRIBUTES.get(); |
| | | final LocalizableMessage message = ERR_LDIF_NO_NEW_RDN.get( |
| | | record.lineNumber, entryDN.toString()); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | final KeyValuePair pair = new KeyValuePair(); |
| | | String ldifLine = record.iterator.next(); |
| | | readLDIFRecordKeyValuePair(record, pair, true); |
| | | if (!toLowerCase(pair.key).equals("newrdn")) |
| | | String ldifLine = readLDIFRecordKeyValuePair(record, pair, true); |
| | | |
| | | if (pair.key == null || !toLowerCase(pair.key).equals("newrdn")) |
| | | { |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Missing newrdn"); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_NEW_RDN.get( |
| | | record.lineNumber, entryDN.toString(), ldifLine); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | |
| | | } |
| | | catch (final LocalizedIllegalArgumentException e) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_DN.get( |
| | | record.lineNumber, ldifLine, e.getMessageObject()); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_NEW_RDN.get( |
| | | record.lineNumber, entryDN.toString(), pair.value); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | // Parse the deleteoldrdn. |
| | | if (!record.iterator.hasNext()) |
| | | { |
| | | // TODO: include line number. |
| | | final LocalizableMessage message = ERR_LDIF_NO_DELETE_OLDRDN_ATTRIBUTE |
| | | .get(); |
| | | final LocalizableMessage message = ERR_LDIF_NO_DELETE_OLD_RDN.get( |
| | | record.lineNumber, entryDN.toString()); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | ldifLine = record.iterator.next(); |
| | | readLDIFRecordKeyValuePair(record, pair, true); |
| | | if (!toLowerCase(pair.key).equals("deleteoldrdn")) |
| | | ldifLine = readLDIFRecordKeyValuePair(record, pair, true); |
| | | if (pair.key == null || !toLowerCase(pair.key).equals("deleteoldrdn")) |
| | | { |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Missing deleteoldrdn"); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_DELETE_OLD_RDN.get( |
| | | record.lineNumber, entryDN.toString(), ldifLine); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | |
| | | } |
| | | else |
| | | { |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_DELETE_OLDRDN_ATTRIBUTE |
| | | .get(pair.value); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_DELETE_OLD_RDN.get( |
| | | record.lineNumber, entryDN.toString(), pair.value); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | | // Parse the newsuperior if present. |
| | | if (record.iterator.hasNext()) |
| | | { |
| | | ldifLine = record.iterator.next(); |
| | | readLDIFRecordKeyValuePair(record, pair, true); |
| | | if (!toLowerCase(pair.key).equals("newsuperior")) |
| | | ldifLine = readLDIFRecordKeyValuePair(record, pair, true); |
| | | if (pair.key == null || !toLowerCase(pair.key).equals("newsuperior")) |
| | | { |
| | | // FIXME: improve error. |
| | | final LocalizableMessage message = LocalizableMessage |
| | | .raw("Missing newsuperior"); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_NEW_SUPERIOR.get( |
| | | record.lineNumber, entryDN.toString(), ldifLine); |
| | | throw DecodeException.error(message); |
| | | } |
| | | |
| | |
| | | } |
| | | catch (final LocalizedIllegalArgumentException e) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_INVALID_DN.get( |
| | | record.lineNumber, ldifLine, e.getMessageObject()); |
| | | final LocalizableMessage message = ERR_LDIF_MALFORMED_NEW_SUPERIOR.get( |
| | | record.lineNumber, entryDN.toString(), pair.value); |
| | | throw DecodeException.error(message); |
| | | } |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2011 ForgeRock AS |
| | | */ |
| | | |
| | | package org.forgerock.opendj.ldif; |
| | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.util.Arrays; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.NoSuchElementException; |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Sets the rejected record listener which should be notified whenever a |
| | | * record is skipped, malformed, or fails schema validation. |
| | | * <p> |
| | | * By default the {@link RejectedRecordListener#FAIL_FAST} listener is used. |
| | | * |
| | | * @param listener |
| | | * The rejected record listener. |
| | | * @return A reference to this {@code LDIFEntryReader}. |
| | | */ |
| | | public LDIFEntryReader setRejectedRecordListener( |
| | | final RejectedRecordListener listener) |
| | | { |
| | | this.rejectedRecordListener = listener; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets the schema which should be used for decoding entries that are read |
| | | * from LDIF. The default schema is used if no other is specified. |
| | | * |
| | |
| | | public LDIFEntryReader setSchema(final Schema schema) |
| | | { |
| | | Validator.ensureNotNull(schema); |
| | | this.schema = schema; |
| | | this.schema = validateSchema ? schema.asStrictSchema() : schema |
| | | .asNonStrictSchema(); |
| | | return this; |
| | | } |
| | | |
| | |
| | | |
| | | /** |
| | | * Specifies whether or not schema validation should be performed for entries |
| | | * that are read from LDIF. The default is {@code true}. |
| | | * that are read from LDIF. |
| | | * <p> |
| | | * When enabled, this LDIF reader will implicitly use a strict schema so that |
| | | * unrecognized attribute types will be detected. |
| | | * <p> |
| | | * Schema validation is disabled by default. |
| | | * |
| | | * @param validateSchema |
| | | * {@code true} if schema validation should be performed, or |
| | |
| | | public LDIFEntryReader setValidateSchema(final boolean validateSchema) |
| | | { |
| | | this.validateSchema = validateSchema; |
| | | this.schema = validateSchema ? schema.asStrictSchema() : schema |
| | | .asNonStrictSchema(); |
| | | return this; |
| | | } |
| | | |
| | |
| | | { |
| | | while (nextEntry == null) |
| | | { |
| | | LDIFRecord record = null; |
| | | |
| | | // Read the set of lines that make up the next entry. |
| | | record = readLDIFRecord(); |
| | | final LDIFRecord 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); |
| | | // Read the DN of the entry and see if it is one that should be |
| | | // included in the import. |
| | | final DN 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; |
| | | } |
| | | // Skip if branch containing the entry DN is excluded. |
| | | if (isBranchExcluded(entryDN)) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_ENTRY_EXCLUDED_BY_DN.get( |
| | | record.lineNumber, entryDN.toString()); |
| | | handleSkippedRecord(record, message); |
| | | continue; |
| | | } |
| | | |
| | | // Use an Entry for the AttributeSequence. |
| | | final Entry entry = new LinkedHashMapEntry(entryDN); |
| | | try |
| | | { |
| | | // Use an Entry for the AttributeSequence. |
| | | final Entry entry = new LinkedHashMapEntry(entryDN); |
| | | final List<LocalizableMessage> schemaErrors = new LinkedList<LocalizableMessage>(); |
| | | while (record.iterator.hasNext()) |
| | | { |
| | | final String ldifLine = record.iterator.next(); |
| | | readLDIFRecordAttributeValue(record, ldifLine, entry); |
| | | readLDIFRecordAttributeValue(record, ldifLine, entry, schemaErrors); |
| | | } |
| | | |
| | | // Skip if the entry is excluded by any filters. |
| | | if (isEntryExcluded(entry)) |
| | | { |
| | | final LocalizableMessage message = ERR_LDIF_ENTRY_EXCLUDED_BY_FILTER |
| | | .get(record.lineNumber, entryDN.toString()); |
| | | handleSkippedRecord(record, message); |
| | | continue; |
| | | } |
| | | |
| | | if (!schemaErrors.isEmpty()) |
| | | { |
| | | handleSchemaValidationFailure(record, schemaErrors); |
| | | continue; |
| | | } |
| | | |
| | | nextEntry = entry; |
| | | } |
| | | catch (final DecodeException e) |
| | | { |
| | | rejectLDIFRecord(record, e.getMessageObject()); |
| | | handleMalformedRecord(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; |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opendj3/legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opendj3/legal-notices/CDDLv1_0.txt. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * Copyright 2011 ForgeRock AS |
| | | */ |
| | | |
| | | package org.forgerock.opendj.ldif; |
| | | |
| | | |
| | | |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A listener interface which is notified whenever records are skipped, |
| | | * malformed, or fail schema validation. |
| | | */ |
| | | public interface RejectedRecordListener |
| | | { |
| | | /** |
| | | * The default handler which ignores skipped records but which terminates |
| | | * processing by throwing a {@code DecodeException} as soon as a record is |
| | | * found to be malformed or rejected due to a schema validation failure. |
| | | */ |
| | | public static final RejectedRecordListener FAIL_FAST = new RejectedRecordListener() |
| | | { |
| | | |
| | | @Override |
| | | public void handleMalformedRecord(final long lineNumber, |
| | | final List<String> ldifRecord, final LocalizableMessage reason) |
| | | throws DecodeException |
| | | { |
| | | // Fail fast. |
| | | throw DecodeException.error(reason); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public void handleSchemaValidationFailure(final long lineNumber, |
| | | final List<String> ldifRecord, final List<LocalizableMessage> reasons) |
| | | throws DecodeException |
| | | { |
| | | // Fail fast - just use first message. |
| | | throw DecodeException.error(reasons.get(0)); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public void handleSkippedRecord(final long lineNumber, |
| | | final List<String> ldifRecord, final LocalizableMessage reason) |
| | | throws DecodeException |
| | | { |
| | | // Ignore skipped records. |
| | | } |
| | | }; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Invoked when a record was rejected because it was malformed in some way and |
| | | * could not be decoded. |
| | | * |
| | | * @param lineNumber |
| | | * The line number within the source location in which the malformed |
| | | * record is located, if known, otherwise {@code -1}. |
| | | * @param ldifRecord |
| | | * An LDIF representation of the malformed record. |
| | | * @param reason |
| | | * The reason why the record is malformed. |
| | | * @throws DecodeException |
| | | * If processing should terminate. |
| | | */ |
| | | void handleMalformedRecord(long lineNumber, List<String> ldifRecord, |
| | | LocalizableMessage reason) throws DecodeException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Invoked when a record was rejected because it does not conform to the |
| | | * schema and schema validation is enabled. |
| | | * |
| | | * @param lineNumber |
| | | * The line number within the source location in which the rejected |
| | | * record is located, if known, otherwise {@code -1}. |
| | | * @param ldifRecord |
| | | * An LDIF representation of the record which failed schema |
| | | * validation. |
| | | * @param reasons |
| | | * The reasons why the record failed schema validation. |
| | | * @throws DecodeException |
| | | * If processing should terminate. |
| | | */ |
| | | void handleSchemaValidationFailure(long lineNumber, List<String> ldifRecord, |
| | | List<LocalizableMessage> reasons) throws DecodeException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Invoked when a record was skipped because it did not match filter criteria |
| | | * defined by the reader. |
| | | * |
| | | * @param lineNumber |
| | | * The line number within the source location in which the skipped |
| | | * record is located, if known, otherwise {@code -1}. |
| | | * @param ldifRecord |
| | | * An LDIF representation of the skipped record. |
| | | * @param reason |
| | | * The reason why the record was skipped. |
| | | * @throws DecodeException |
| | | * If processing should terminate. |
| | | */ |
| | | void handleSkippedRecord(long lineNumber, List<String> ldifRecord, |
| | | LocalizableMessage reason) throws DecodeException; |
| | | |
| | | } |
| | |
| | | failed and will be removed from the schema: %s |
| | | ERR_NO_SUBSCHEMA_SUBENTRY_ATTR=The entry %s does not include \ |
| | | a subschemaSubentry attribute |
| | | ERR_ATTRIBUTE_DESCRIPTION_TYPE_NOT_FOUND=The attribute description "%s" \ |
| | | could not be parsed due to the following reason: %s |
| | | ERR_RDN_TYPE_NOT_FOUND=The RDN "%s" could not be parsed due to the \ |
| | | following reason: %s |
| | | ERR_DN_TYPE_NOT_FOUND=The DN "%s" could not be parsed due to the \ |
| | |
| | | ERR_LDIF_COULD_NOT_BASE64_DECODE_ATTR=Unable to parse LDIF entry %s \ |
| | | starting at line %d because it was not possible to base64-decode the \ |
| | | attribute on line "%s": %s |
| | | WARN_LDIF_DUPLICATE_ATTR=Entry %s read from LDIF starting at line %d \ |
| | | includes a duplicate attribute %s with value %s. The second occurrence of \ |
| | | that attribute value has been skipped |
| | | ERR_LDIF_MULTIPLE_VALUES_FOR_SINGLE_VALUED_ATTR=Entry %s starting at \ |
| | | line %d includes multiple values for single-valued attribute %s |
| | | ERR_LDIF_INVALID_URL=Unable to parse LDIF entry %s starting at line \ |
| | | %d because the value of attribute %s was to be read from a URL but the URL \ |
| | | was invalid: %s |
| | | ERR_LDIF_URL_IO_ERROR=Unable to parse LDIF entry %s starting at line \ |
| | | %d because the value of attribute %s was to be read from URL %s but an error \ |
| | | occurred while trying to read that content: %s |
| | | ERR_LDIF_INVALID_DELETE_ATTRIBUTES=Error in the LDIF change record \ |
| | | entry. Invalid attributes specified for the delete operation |
| | | ERR_LDIF_NO_MOD_DN_ATTRIBUTES=Error in the LDIF change record \ |
| | | entry. No attributes specified for the mod DN operation |
| | | ERR_LDIF_NO_DELETE_OLDRDN_ATTRIBUTE=Error in the LDIF change record \ |
| | | entry. No delete old RDN attribute specified for the mod DN operation |
| | | ERR_LDIF_INVALID_DELETE_OLDRDN_ATTRIBUTE=Error in the LDIF change \ |
| | | record entry. Invalid value "%s" for the delete old RDN attribute specified \ |
| | | for the mod DN operation |
| | | ERR_LDIF_INVALID_CHANGERECORD_ATTRIBUTE=Error in the LDIF change \ |
| | | record entry. Invalid attribute "%s" specified. Expecting attribute "%s" |
| | | ERR_LDIF_INVALID_MODIFY_ATTRIBUTE=Error in the LDIF change record \ |
| | | entry. Invalid attribute "%s" specified. Expecting one of the following \ |
| | | attributes "%s" |
| | | ERR_LDIF_INVALID_CHANGETYPE_ATTRIBUTE=Error in the LDIF change \ |
| | | record entry. Invalid value "%s" for the changetype specified. Expecting one \ |
| | | of the following values "%s" |
| | | ERR_LDAPURL_NO_SCHEME=The provided string "%s" cannot be decoded \ |
| | | as an LDAP URL because it does not contain a protocol scheme |
| | | ERR_LDAPURL_BAD_SCHEME=The provided string "%s" cannot be decoded \ |
| | |
| | | ERR_LDAPURL_INVALID_HEX_BYTE=The provided URL component "%s" could \ |
| | | not be decoded because the character at byte %d was not a valid hexadecimal \ |
| | | digit |
| | | WARN_LDIF_VALUE_VIOLATES_SYNTAX=Entry %s read from LDIF starting at \ |
| | | line %d includes value "%s" for attribute %s that is invalid according to the \ |
| | | associated syntax: %s |
| | | ERR_LDIF_INVALID_ATTR_OPTION=Unable to parse LDIF entry %s starting \ |
| | | at line %d because it has an invalid binary option for attribute %s |
| | | ERR_INVALID_ESCAPE_CHAR=The value %s cannot be decoded because %c \ |
| | | is not a valid escape character |
| | | WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND=The provided LDIF \ |
| | |
| | | the optional attribute "%s" which is not defined in the schema |
| | | WARN_ATTR_SYNTAX_NOT_IMPLEMENTED1=The "%s" syntax with OID %s is not \ |
| | | implemented. It will be substituted by the default syntax with OID %s |
| | | ERR_LDIF_ENTRY_EXCLUDED_BY_DN=Skipping LDIF entry starting at line %d with \ |
| | | distinguished name "%s" because it is within an excluded branch |
| | | ERR_LDIF_ENTRY_EXCLUDED_BY_FILTER=Skipping LDIF entry starting at line %d with \ |
| | | distinguished name "%s" because it does not meet the filter criteria |
| | | ERR_LDIF_CHANGE_EXCLUDED_BY_DN=Skipping LDIF change record starting at line %d \ |
| | | with distinguished name "%s" because it is within an excluded branch |
| | | ERR_LDIF_NO_CHANGE_TYPE=Unable to parse LDIF change record starting at line %d \ |
| | | with distinguished name "%s" because there was no change type |
| | | ERR_LDIF_MALFORMED_CHANGE_TYPE=Unable to parse LDIF change record starting at line %d \ |
| | | with distinguished name "%s" because it contained a malformed changetype \ |
| | | "%s" |
| | | ERR_LDIF_BAD_CHANGE_TYPE=Unable to parse LDIF change record starting at line %d \ |
| | | with distinguished name "%s" because it contained an unrecognized changetype \ |
| | | "%s". The changetype must be one of add, delete, modify, modrdn, or moddn |
| | | ERR_LDIF_MALFORMED_DELETE=Unable to parse LDIF delete record starting at line %d \ |
| | | with distinguished name "%s" because it contained additional lines after the \ |
| | | changetype when none were expected |
| | | ERR_LDIF_BAD_MODIFICATION_TYPE=Unable to parse LDIF modify record starting at line %d \ |
| | | with distinguished name "%s" because it contained an unrecognized modification type \ |
| | | "%s". The modification type must be one of add, delete, replace, or increment |
| | | ERR_LDIF_MALFORMED_MODIFICATION_TYPE=Unable to parse LDIF modify record starting at line %d \ |
| | | with distinguished name "%s" because it contained a malformed modification type \ |
| | | "%s" |
| | | ERR_LDIF_UNKNOWN_ATTRIBUTE_TYPE=Rejecting the LDIF change record \ |
| | | starting at line %d with distinguished name "%s" because it contains an \ |
| | | unrecognized attribute type "%s" |
| | | ERR_LDIF_MALFORMED_ATTRIBUTE_NAME=Unable to parse LDIF change record \ |
| | | starting at line %d with distinguished name "%s" because it contained a \ |
| | | malformed attribute description "%s" |
| | | ERR_LDIF_UNEXPECTED_BINARY_OPTION=Unable to parse LDIF change record starting \ |
| | | at line %d with distinguished name "%s" because it has an unexpected binary \ |
| | | option for attribute %s |
| | | ERR_LDIF_ATTRIBUTE_NAME_MISMATCH=Unable to parse LDIF change record \ |
| | | starting at line %d with distinguished name "%s" because it contained a \ |
| | | an unexpected attribute "%s" when "%s" was expected |
| | | WARN_LDIF_MALFORMED_ATTRIBUTE_VALUE=Rejecting the LDIF change record \ |
| | | starting at line %d with distinguished name "%s" because it includes the \ |
| | | value "%s" for attribute "%s" which is invalid according to the syntax: %s |
| | | WARN_LDIF_DUPLICATE_ATTRIBUTE_VALUE=Rejecting the LDIF change record \ |
| | | starting at line %d with distinguished name "%s" because it includes a \ |
| | | duplicate attribute "%s" with value "%s" |
| | | ERR_LDIF_MULTI_VALUED_SINGLE_VALUED_ATTRIBUTE=Rejecting the LDIF change record \ |
| | | starting at line %d with distinguished name "%s" because it includes multiple \ |
| | | values for single-valued attribute "%s" |
| | | ERR_LDIF_NO_NEW_RDN=Unable to parse LDIF modify DN record starting at line %d \ |
| | | with distinguished name "%s" because there was no new RDN |
| | | ERR_LDIF_MALFORMED_NEW_RDN=Unable to parse LDIF modify DN record starting at line %d \ |
| | | with distinguished name "%s" because it contained a malformed new RDN "%s" |
| | | ERR_LDIF_NO_DELETE_OLD_RDN=Unable to parse LDIF modify DN record starting at line %d \ |
| | | with distinguished name "%s" because there was no deleteoldrdn field |
| | | ERR_LDIF_MALFORMED_DELETE_OLD_RDN=Unable to parse LDIF modify DN record starting at line %d \ |
| | | with distinguished name "%s" because it contained a malformed deleteoldrdn "%s" |
| | | ERR_LDIF_MALFORMED_NEW_SUPERIOR=Unable to parse LDIF modify DN record starting at line %d \ |
| | | with distinguished name "%s" because it contained a malformed newsuperior "%s" |
| | | |
| | |
| | | + "caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch " |
| | | + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )", |
| | | false); |
| | | final Schema testSchema = builder.toSchema().nonStrict(); |
| | | final Schema testSchema = builder.toSchema().asNonStrictSchema(); |
| | | assertThat(testSchema.getWarnings()).isEmpty(); |
| | | Schema.setDefaultSchema(testSchema); |
| | | |
| | |
| | | SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema()) |
| | | .setSchemaCompatOptions(SchemaCompatOptions.defaultOptions() |
| | | .allowMalformedNamesAndOptions(allowIllegalCharacters)); |
| | | Schema schema = builder.toSchema().nonStrict(); |
| | | Schema schema = builder.toSchema().asNonStrictSchema(); |
| | | AttributeDescription.valueOf(atd, schema); |
| | | } |
| | | |
| | |
| | | SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema()) |
| | | .setSchemaCompatOptions(SchemaCompatOptions.defaultOptions() |
| | | .allowMalformedNamesAndOptions(allowIllegalCharacters)); |
| | | Schema schema = builder.toSchema().nonStrict(); |
| | | Schema schema = builder.toSchema().asNonStrictSchema(); |
| | | AttributeDescription.valueOf(atd, schema); |
| | | } |
| | | |
| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opendj3/legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opendj3/legal-notices/CDDLv1_0.txt. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * |
| | | * Copyright 2011 ForgeRock AS |
| | | */ |
| | | |
| | | package org.forgerock.opendj.ldif; |
| | | |
| | | |
| | | |
| | | import static org.fest.assertions.Assertions.assertThat; |
| | | import static org.mockito.Matchers.*; |
| | | import static org.mockito.Mockito.*; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.Iterator; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.ldap.*; |
| | | import org.forgerock.opendj.ldap.requests.AddRequest; |
| | | import org.forgerock.opendj.ldap.requests.DeleteRequest; |
| | | import org.forgerock.opendj.ldap.requests.ModifyDNRequest; |
| | | import org.forgerock.opendj.ldap.requests.ModifyRequest; |
| | | import org.testng.annotations.Test; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class tests the LDIFChangeRecordReader functionality. |
| | | */ |
| | | public final class LDIFChangeRecordReaderTestCase extends LDIFTestCase |
| | | { |
| | | /** |
| | | * Tests reading a valid add change record with a changetype. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testReadAddRecordWithChangeType() throws Exception |
| | | { |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "changetype: add", |
| | | "objectClass: top", |
| | | "objectClass: domainComponent", |
| | | "dc: example" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | ChangeRecord record = reader.readChangeRecord(); |
| | | assertThat(record).isInstanceOf(AddRequest.class); |
| | | AddRequest addRequest = (AddRequest) record; |
| | | assertThat((Object) addRequest.getName()).isEqualTo( |
| | | DN.valueOf("dc=example,dc=com")); |
| | | assertThat( |
| | | addRequest.containsAttribute("objectClass", "top", "domainComponent")) |
| | | .isTrue(); |
| | | assertThat(addRequest.containsAttribute("dc", "example")).isTrue(); |
| | | assertThat(addRequest.getAttributeCount()).isEqualTo(2); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a valid add change record without a changetype. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testReadAddRecordWithoutChangeType() throws Exception |
| | | { |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: domainComponent", |
| | | "dc: example" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | ChangeRecord record = reader.readChangeRecord(); |
| | | assertThat(record).isInstanceOf(AddRequest.class); |
| | | AddRequest addRequest = (AddRequest) record; |
| | | assertThat((Object) addRequest.getName()).isEqualTo( |
| | | DN.valueOf("dc=example,dc=com")); |
| | | assertThat( |
| | | addRequest.containsAttribute("objectClass", "top", "domainComponent")) |
| | | .isTrue(); |
| | | assertThat(addRequest.containsAttribute("dc", "example")).isTrue(); |
| | | assertThat(addRequest.getAttributeCount()).isEqualTo(2); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a valid modify change record. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testReadModifyRecord() throws Exception |
| | | { |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "changetype: modify", |
| | | "add: description", |
| | | "-", |
| | | "add: description", |
| | | "description: value1", |
| | | "-", |
| | | "add: description", |
| | | "description: value1", |
| | | "description: value2", |
| | | "-", |
| | | "delete: description", |
| | | "-", |
| | | "delete: description", |
| | | "description: value1", |
| | | "-", |
| | | "delete: description", |
| | | "description: value1", |
| | | "description: value2", |
| | | "-", |
| | | "replace: description", |
| | | "-", |
| | | "replace: description", |
| | | "description: value1", |
| | | "-", |
| | | "replace: description", |
| | | "description: value1", |
| | | "description: value2", |
| | | "-", |
| | | "increment: description", |
| | | "description: 1" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | ChangeRecord record = reader.readChangeRecord(); |
| | | assertThat(record).isInstanceOf(ModifyRequest.class); |
| | | ModifyRequest modifyRequest = (ModifyRequest) record; |
| | | assertThat((Object) modifyRequest.getName()).isEqualTo( |
| | | DN.valueOf("dc=example,dc=com")); |
| | | |
| | | Iterator<Modification> changes = modifyRequest.getModifications() |
| | | .iterator(); |
| | | Modification modification; |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.ADD); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.ADD); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description", "value1")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.ADD); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description", "value1", "value2")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.DELETE); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.DELETE); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description", "value1")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.DELETE); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description", "value1", "value2")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.REPLACE); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.REPLACE); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description", "value1")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.REPLACE); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description", "value1", "value2")); |
| | | |
| | | modification = changes.next(); |
| | | assertThat(modification.getModificationType()).isEqualTo( |
| | | ModificationType.INCREMENT); |
| | | assertThat(modification.getAttribute()).isEqualTo( |
| | | new LinkedAttribute("description", "1")); |
| | | |
| | | assertThat(changes.hasNext()).isFalse(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a valid delete change record. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testReadDeleteRecord() throws Exception |
| | | { |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "changetype: delete" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | ChangeRecord record = reader.readChangeRecord(); |
| | | assertThat(record).isInstanceOf(DeleteRequest.class); |
| | | DeleteRequest deleteRequest = (DeleteRequest) record; |
| | | assertThat((Object) deleteRequest.getName()).isEqualTo( |
| | | DN.valueOf("dc=example,dc=com")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a valid moddn change record. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testReadModdnRecordWithoutNewSuperior() throws Exception |
| | | { |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "changetype: moddn", |
| | | "newrdn: dc=eggsample", |
| | | "deleteoldrdn: true" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | ChangeRecord record = reader.readChangeRecord(); |
| | | assertThat(record).isInstanceOf(ModifyDNRequest.class); |
| | | ModifyDNRequest modifyDNRequest = (ModifyDNRequest) record; |
| | | assertThat((Object) modifyDNRequest.getName()).isEqualTo( |
| | | DN.valueOf("dc=example,dc=com")); |
| | | assertThat((Object) modifyDNRequest.getNewRDN()).isEqualTo( |
| | | RDN.valueOf("dc=eggsample")); |
| | | assertThat(modifyDNRequest.isDeleteOldRDN()).isTrue(); |
| | | assertThat(modifyDNRequest.getNewSuperior()).isNull(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a valid moddn change record. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testReadModdnRecordWithNewSuperior() throws Exception |
| | | { |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "changetype: moddn", |
| | | "newrdn: dc=eggsample", |
| | | "deleteoldrdn: true", |
| | | "newsuperior: dc=org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | ChangeRecord record = reader.readChangeRecord(); |
| | | assertThat(record).isInstanceOf(ModifyDNRequest.class); |
| | | ModifyDNRequest modifyDNRequest = (ModifyDNRequest) record; |
| | | assertThat((Object) modifyDNRequest.getName()).isEqualTo( |
| | | DN.valueOf("dc=example,dc=com")); |
| | | assertThat((Object) modifyDNRequest.getNewRDN()).isEqualTo( |
| | | RDN.valueOf("dc=eggsample")); |
| | | assertThat(modifyDNRequest.isDeleteOldRDN()).isTrue(); |
| | | assertThat((Object) modifyDNRequest.getNewSuperior()).isEqualTo( |
| | | DN.valueOf("dc=org")); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a malformed record invokes the rejected record listener. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testRejectedRecordListenerMalformedFirstRecord() throws Exception |
| | | { |
| | | RejectedRecordListener listener = mock(RejectedRecordListener.class); |
| | | |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: baddn", |
| | | "changetype: add", |
| | | "objectClass: top", |
| | | "objectClass: domainComponent", |
| | | "dc: example" |
| | | ).setRejectedRecordListener(listener); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | |
| | | verify(listener).handleMalformedRecord( |
| | | eq(1L), |
| | | eq(Arrays.asList("dn: baddn", "changetype: add", "objectClass: top", |
| | | "objectClass: domainComponent", "dc: example")), |
| | | any(LocalizableMessage.class)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a malformed record invokes the rejected record listener. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testRejectedRecordListenerMalformedSecondRecord() |
| | | throws Exception |
| | | { |
| | | RejectedRecordListener listener = mock(RejectedRecordListener.class); |
| | | |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "changetype: add", |
| | | "objectClass: top", |
| | | "objectClass: domainComponent", |
| | | "dc: example", |
| | | "", |
| | | "dn: baddn", |
| | | "changetype: add", |
| | | "objectClass: top", |
| | | "objectClass: domainComponent", |
| | | "dc: example" |
| | | ).setRejectedRecordListener(listener); |
| | | // @formatter:on |
| | | |
| | | reader.readChangeRecord(); // Skip good record. |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | |
| | | verify(listener).handleMalformedRecord( |
| | | eq(7L), |
| | | eq(Arrays.asList("dn: baddn", "changetype: add", "objectClass: top", |
| | | "objectClass: domainComponent", "dc: example")), |
| | | any(LocalizableMessage.class)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a skipped record invokes the rejected record listener. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testRejectedRecordListenerSkipsRecord() throws Exception |
| | | { |
| | | RejectedRecordListener listener = mock(RejectedRecordListener.class); |
| | | |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "changetype: add", |
| | | "objectClass: top", |
| | | "objectClass: domainComponent", |
| | | "dc: example" |
| | | ).setRejectedRecordListener(listener).setExcludeBranch(DN.valueOf("dc=com")); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | |
| | | verify(listener) |
| | | .handleSkippedRecord( |
| | | eq(1L), |
| | | eq(Arrays.asList("dn: dc=example,dc=com", "changetype: add", |
| | | "objectClass: top", "objectClass: domainComponent", |
| | | "dc: example")), any(LocalizableMessage.class)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests reading a record which does not conform to the schema invokes the |
| | | * rejected record listener. |
| | | * |
| | | * @throws Exception |
| | | * if an unexpected error occurred. |
| | | */ |
| | | @Test |
| | | public void testRejectedRecordListenerRejectsBadSchemaRecord() |
| | | throws Exception |
| | | { |
| | | RejectedRecordListener listener = mock(RejectedRecordListener.class); |
| | | |
| | | // @formatter:off |
| | | LDIFChangeRecordReader reader = new LDIFChangeRecordReader( |
| | | "dn: dc=example,dc=com", |
| | | "changetype: add", |
| | | "objectClass: top", |
| | | "objectClass: domainComponent", |
| | | "dc: example", |
| | | "xxx: unknown attribute" |
| | | ).setRejectedRecordListener(listener).setValidateSchema(true); |
| | | // @formatter:on |
| | | |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | |
| | | verify(listener).handleSchemaValidationFailure( |
| | | eq(1L), |
| | | eq(Arrays.asList("dn: dc=example,dc=com", "changetype: add", |
| | | "objectClass: top", "objectClass: domainComponent", "dc: example", |
| | | "xxx: unknown attribute")), anyListOf(LocalizableMessage.class)); |
| | | } |
| | | } |