Fix OPENDJ-619 : Reduce the memory utilization of LDIF.diff(EntryReader, EntryReader) in the SDK
| | |
| | | |
| | | package org.forgerock.opendj.ldap; |
| | | |
| | | import static com.forgerock.opendj.util.StaticUtils.getBytes; |
| | | import static org.forgerock.opendj.ldap.CoreMessages.ERR_DN_TYPE_NOT_FOUND; |
| | | |
| | | import java.util.Iterator; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.Map; |
| | | import java.util.NoSuchElementException; |
| | | import java.util.TreeSet; |
| | | import java.util.WeakHashMap; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizedIllegalArgumentException; |
| | | import org.forgerock.opendj.ldap.schema.MatchingRule; |
| | | import org.forgerock.opendj.ldap.schema.Schema; |
| | | import org.forgerock.opendj.ldap.schema.Syntax; |
| | | import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException; |
| | | |
| | | import com.forgerock.opendj.util.StaticUtils; |
| | | import com.forgerock.opendj.util.SubstringReader; |
| | | import com.forgerock.opendj.util.Validator; |
| | | |
| | |
| | | } |
| | | return stringValue; |
| | | } |
| | | |
| | | /** |
| | | * Returns the normalized string representation of a DN. |
| | | * |
| | | * @return The normalized string representation of the provided DN. |
| | | */ |
| | | public String toNormalizedString() { |
| | | final StringBuilder builder = new StringBuilder(this.size()); |
| | | if (rdn() == null) { |
| | | return builder.toString(); |
| | | } |
| | | |
| | | int i = this.size() - 1; |
| | | normalizeRDN(builder, parent(i).rdn()); |
| | | for (i--; i >= 0; i--) { |
| | | final RDN rdn = parent(i).rdn(); |
| | | // Only add a separator if the RDN is not RDN.maxValue(). |
| | | if (rdn.size() != 0) { |
| | | builder.append('\u0000'); |
| | | } |
| | | normalizeRDN(builder, rdn); |
| | | } |
| | | return builder.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the normalized string representation of a RDN. |
| | | * |
| | | * @param builder |
| | | * The StringBuilder to use to construct the normalized string. |
| | | * @param rdn |
| | | * The RDN. |
| | | * @return The normalized string representation of the provided RDN. |
| | | */ |
| | | private static StringBuilder normalizeRDN(final StringBuilder builder, final RDN rdn) { |
| | | final int sz = rdn.size(); |
| | | switch (sz) { |
| | | case 0: |
| | | // Handle RDN.maxValue(). |
| | | builder.append('\u0001'); |
| | | break; |
| | | case 1: |
| | | normalizeAVA(builder, rdn.getFirstAVA()); |
| | | break; |
| | | default: |
| | | // Need to sort the AVAs before comparing. |
| | | TreeSet<AVA> a = new TreeSet<AVA>(); |
| | | for (AVA ava : rdn) { |
| | | a.add(ava); |
| | | } |
| | | Iterator<AVA> i = a.iterator(); |
| | | // Normalize the first AVA. |
| | | normalizeAVA(builder, i.next()); |
| | | while (i.hasNext()) { |
| | | builder.append('\u0001'); |
| | | normalizeAVA(builder, i.next()); |
| | | } |
| | | break; |
| | | } |
| | | return builder; |
| | | } |
| | | |
| | | /** |
| | | * Returns the normalized string representation of an AVA. |
| | | * |
| | | * @param builder |
| | | * The StringBuilder to use to construct the normalized string. |
| | | * @param ava |
| | | * The AVA. |
| | | * @return The normalized string representation of the provided AVA. |
| | | */ |
| | | private static StringBuilder normalizeAVA(final StringBuilder builder, final AVA ava) { |
| | | ByteString value = ava.getAttributeValue(); |
| | | final MatchingRule matchingRule = ava.getAttributeType().getEqualityMatchingRule(); |
| | | if (matchingRule != null) { |
| | | try { |
| | | value = matchingRule.normalizeAttributeValue(ava.getAttributeValue()); |
| | | } catch (final DecodeException de) { |
| | | // Ignore - we'll drop back to the user provided value. |
| | | } |
| | | } |
| | | |
| | | if (!ava.getAttributeType().getNames().iterator().hasNext()) { |
| | | builder.append(ava.getAttributeType().getOID()); |
| | | builder.append("=#"); |
| | | StaticUtils.toHex(value, builder); |
| | | } else { |
| | | final String name = ava.getAttributeType().getNameOrOID(); |
| | | // Normalizing. |
| | | StaticUtils.toLowerCase(name, builder); |
| | | |
| | | builder.append("="); |
| | | |
| | | final Syntax syntax = ava.getAttributeType().getSyntax(); |
| | | if (!syntax.isHumanReadable()) { |
| | | builder.append("#"); |
| | | StaticUtils.toHex(value, builder); |
| | | } else { |
| | | final String str = value.toString(); |
| | | if (str.length() == 0) { |
| | | return builder; |
| | | } |
| | | char c = str.charAt(0); |
| | | int startPos = 0; |
| | | if ((c == ' ') || (c == '#')) { |
| | | builder.append('\\'); |
| | | builder.append(c); |
| | | startPos = 1; |
| | | } |
| | | final int length = str.length(); |
| | | for (int si = startPos; si < length; si++) { |
| | | c = str.charAt(si); |
| | | if (c < ' ') { |
| | | for (final byte b : getBytes(String.valueOf(c))) { |
| | | builder.append('\\'); |
| | | builder.append(StaticUtils.byteToLowerHex(b)); |
| | | } |
| | | } else { |
| | | if ((c == ' ' && si == length - 1) |
| | | || (c == '"' || c == '+' || c == ',' || c == ';' || c == '<' |
| | | || c == '=' || c == '>' || c == '\\' || c == '\u0000')) { |
| | | builder.append('\\'); |
| | | } |
| | | builder.append(c); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return builder; |
| | | } |
| | | |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2011-2012 ForgeRock AS. |
| | | */ |
| | | package org.forgerock.opendj.ldap.schema; |
| | | |
| | | import static com.forgerock.opendj.util.StaticUtils.getBytes; |
| | | |
| | | import java.util.Iterator; |
| | | import java.util.TreeSet; |
| | | |
| | | import org.forgerock.i18n.LocalizedIllegalArgumentException; |
| | | import org.forgerock.opendj.ldap.AVA; |
| | | import org.forgerock.opendj.ldap.ByteSequence; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.RDN; |
| | | |
| | | import com.forgerock.opendj.util.StaticUtils; |
| | | |
| | | /** |
| | | * This class defines the distinguishedNameMatch matching rule defined in X.520 |
| | | * and referenced in RFC 2252. |
| | | */ |
| | | final class DistinguishedNameEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl { |
| | | /** |
| | | * Returns the normalized string representation of an AVA. |
| | | * |
| | | * @param builder |
| | | * The StringBuilder to use to construct the normalized string. |
| | | * @param ava |
| | | * The AVA. |
| | | * @return The normalized string representation of the provided AVA. |
| | | */ |
| | | private static StringBuilder normalizeAVA(final StringBuilder builder, final AVA ava) { |
| | | ByteString value = ava.getAttributeValue(); |
| | | final MatchingRule matchingRule = ava.getAttributeType().getEqualityMatchingRule(); |
| | | if (matchingRule != null) { |
| | | try { |
| | | value = matchingRule.normalizeAttributeValue(ava.getAttributeValue()); |
| | | } catch (final DecodeException de) { |
| | | // Ignore - we'll drop back to the user provided value. |
| | | } |
| | | } |
| | | |
| | | if (!ava.getAttributeType().getNames().iterator().hasNext()) { |
| | | builder.append(ava.getAttributeType().getOID()); |
| | | builder.append("=#"); |
| | | StaticUtils.toHex(value, builder); |
| | | } else { |
| | | final String name = ava.getAttributeType().getNameOrOID(); |
| | | // Normalizing. |
| | | StaticUtils.toLowerCase(name, builder); |
| | | |
| | | builder.append("="); |
| | | |
| | | final Syntax syntax = ava.getAttributeType().getSyntax(); |
| | | if (!syntax.isHumanReadable()) { |
| | | builder.append("#"); |
| | | StaticUtils.toHex(value, builder); |
| | | } else { |
| | | final String str = value.toString(); |
| | | if (str.length() == 0) { |
| | | return builder; |
| | | } |
| | | char c = str.charAt(0); |
| | | int startPos = 0; |
| | | if ((c == ' ') || (c == '#')) { |
| | | builder.append('\\'); |
| | | builder.append(c); |
| | | startPos = 1; |
| | | } |
| | | final int length = str.length(); |
| | | for (int si = startPos; si < length; si++) { |
| | | c = str.charAt(si); |
| | | if (c < ' ') { |
| | | for (final byte b : getBytes(String.valueOf(c))) { |
| | | builder.append('\\'); |
| | | builder.append(StaticUtils.byteToLowerHex(b)); |
| | | } |
| | | } else { |
| | | if ((c == ' ' && si == length - 1) |
| | | || (c == '"' || c == '+' || c == ',' || c == ';' || c == '<' |
| | | || c == '=' || c == '>' || c == '\\' || c == '\u0000')) { |
| | | builder.append('\\'); |
| | | } |
| | | builder.append(c); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return builder; |
| | | } |
| | | |
| | | /** |
| | | * Returns the normalized string representation of a DN. |
| | | * |
| | | * @param builder |
| | | * The StringBuilder to use to construct the normalized string. |
| | | * @param dn |
| | | * The DN. |
| | | * @return The normalized string representation of the provided DN. |
| | | */ |
| | | private static StringBuilder normalizeDN(final StringBuilder builder, final DN dn) { |
| | | if (dn.rdn() == null) { |
| | | return builder; |
| | | } |
| | | |
| | | int i = dn.size() - 1; |
| | | normalizeRDN(builder, dn.parent(i).rdn()); |
| | | for (i--; i >= 0; i--) { |
| | | builder.append('\u0000'); |
| | | normalizeRDN(builder, dn.parent(i).rdn()); |
| | | } |
| | | return builder; |
| | | } |
| | | |
| | | /** |
| | | * Returns the normalized string representation of a RDN. |
| | | * |
| | | * @param builder |
| | | * The StringBuilder to use to construct the normalized string. |
| | | * @param rdn |
| | | * The RDN. |
| | | * @return The normalized string representation of the provided RDN. |
| | | */ |
| | | private static StringBuilder normalizeRDN(final StringBuilder builder, final RDN rdn) { |
| | | final int sz = rdn.size(); |
| | | if (sz == 1) { |
| | | return normalizeAVA(builder, rdn.getFirstAVA()); |
| | | } else { |
| | | // Need to sort the AVAs before comparing. |
| | | TreeSet<AVA> a = new TreeSet<AVA>(); |
| | | for (AVA ava : rdn) { |
| | | a.add(ava); |
| | | } |
| | | Iterator<AVA> i = a.iterator(); |
| | | // Normalize the first AVA. |
| | | normalizeAVA(builder, i.next()); |
| | | while (i.hasNext()) { |
| | | builder.append('\u0001'); |
| | | normalizeAVA(builder, i.next()); |
| | | } |
| | | |
| | | return builder; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | |
| | | throws DecodeException { |
| | | try { |
| | | DN dn = DN.valueOf(value.toString(), schema.asNonStrictSchema()); |
| | | StringBuilder builder = new StringBuilder(value.length()); |
| | | return ByteString.valueOf(normalizeDN(builder, dn)); |
| | | return ByteString.valueOf(dn.toNormalizedString()); |
| | | } catch (final LocalizedIllegalArgumentException e) { |
| | | throw DecodeException.error(e.getMessageObject()); |
| | | } |
| | |
| | | import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_DELETE; |
| | | import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_MODIFY; |
| | | import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_MODIFYDN; |
| | | import static com.forgerock.opendj.util.StaticUtils.getBytes; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.NoSuchElementException; |
| | | import java.util.SortedMap; |
| | | import java.util.TreeMap; |
| | | |
| | | import org.forgerock.opendj.asn1.ASN1; |
| | | import org.forgerock.opendj.asn1.ASN1Reader; |
| | | import org.forgerock.opendj.asn1.ASN1Writer; |
| | | import org.forgerock.opendj.ldap.AVA; |
| | | import org.forgerock.opendj.ldap.Attribute; |
| | | import org.forgerock.opendj.ldap.AttributeDescription; |
| | | import org.forgerock.opendj.ldap.Attributes; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ByteStringBuilder; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | |
| | | import org.forgerock.opendj.ldap.requests.ModifyRequest; |
| | | import org.forgerock.opendj.ldap.requests.Requests; |
| | | import org.forgerock.opendj.ldap.requests.SearchRequest; |
| | | import org.forgerock.opendj.ldap.responses.Responses; |
| | | import org.forgerock.opendj.ldap.responses.SearchResultEntry; |
| | | import org.forgerock.opendj.ldap.schema.AttributeUsage; |
| | | import org.forgerock.opendj.ldap.schema.Schema; |
| | | |
| | | import com.forgerock.opendj.ldap.LDAPUtils; |
| | | |
| | | /** |
| | | * This class contains common utility methods for creating and manipulating |
| | | * readers and writers. |
| | |
| | | // @formatter:on |
| | | |
| | | /** |
| | | * Comparator ordering the DN ASC. |
| | | */ |
| | | private static final Comparator<byte[][]> DN_ORDER2 = new Comparator<byte[][]>() { |
| | | public int compare(byte[][] b1, byte[][] b2) { |
| | | return DN_ORDER.compare(b1[0], b2[0]); |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * Comparator ordering the DN ASC. |
| | | */ |
| | | private static final Comparator<byte[]> DN_ORDER = new Comparator<byte[]>() { |
| | | public int compare(byte[] b1, byte[] b2) { |
| | | final ByteString bs = ByteString.valueOf(b1); |
| | | final ByteString bs2 = ByteString.valueOf(b2); |
| | | return bs.compareTo(bs2); |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * Copies the content of {@code input} to {@code output}. This method does |
| | | * not close {@code input} or {@code output}. |
| | | * |
| | |
| | | */ |
| | | public static ChangeRecordReader diff(final EntryReader source, final EntryReader target) |
| | | throws IOException { |
| | | final SortedMap<DN, Entry> sourceEntries = readEntries(source); |
| | | final SortedMap<DN, Entry> targetEntries = readEntries(target); |
| | | final Iterator<Entry> sourceIterator = sourceEntries.values().iterator(); |
| | | final Iterator<Entry> targetIterator = targetEntries.values().iterator(); |
| | | |
| | | final List<byte[][]> source2 = readEntriesAsList(source); |
| | | final List<byte[][]> target2 = readEntriesAsList(target); |
| | | final Iterator<byte[][]> sourceIterator = source2.iterator(); |
| | | final Iterator<byte[][]> targetIterator = target2.iterator(); |
| | | |
| | | return new ChangeRecordReader() { |
| | | private Entry sourceEntry = nextEntry(sourceIterator); |
| | |
| | | } |
| | | } |
| | | |
| | | private Entry nextEntry(final Iterator<Entry> i) { |
| | | return i.hasNext() ? i.next() : null; |
| | | private Entry nextEntry(final Iterator<byte[][]> i) throws IOException { |
| | | if (i.hasNext()) { |
| | | return decodeEntry(i.next()[1]); |
| | | } |
| | | return null; |
| | | } |
| | | }; |
| | | |
| | | } |
| | | |
| | | /** |
| | |
| | | * <b>NOTE:</b> this method reads the content of {@code input} into memory |
| | | * before applying the changes, and is therefore not suited for use in cases |
| | | * where a very large number of entries are to be patched. |
| | | * <p> |
| | | * <b>NOTE:</b> this method will not perform modifications required in order |
| | | * to maintain referential integrity. In particular, if an entry references |
| | | * another entry using a DN valued attribute and the referenced entry is |
| | | * deleted, then the DN reference will not be removed. The same applies to |
| | | * renamed entries and their references. |
| | | * |
| | | * @param input |
| | | * The entry reader containing the set of entries to be patched. |
| | |
| | | * <b>NOTE:</b> this method reads the content of {@code input} into memory |
| | | * before applying the changes, and is therefore not suited for use in cases |
| | | * where a very large number of entries are to be patched. |
| | | * <p> |
| | | * <b>NOTE:</b> this method will not perform modifications required in order |
| | | * to maintain referential integrity. In particular, if an entry references |
| | | * another entry using a DN valued attribute and the referenced entry is |
| | | * deleted, then the DN reference will not be removed. The same applies to |
| | | * renamed entries and their references. |
| | | * |
| | | * @param input |
| | | * The entry reader containing the set of entries to be patched. |
| | |
| | | */ |
| | | public static EntryReader patch(final EntryReader input, final ChangeRecordReader patch, |
| | | final RejectedChangeRecordListener listener) throws IOException { |
| | | final SortedMap<DN, Entry> entries = readEntries(input); |
| | | final SortedMap<byte[], byte[]> entries = readEntriesAsMap(input); |
| | | |
| | | while (patch.hasNext()) { |
| | | final ChangeRecord change = patch.readChangeRecord(); |
| | | final DN changeDN = change.getName(); |
| | | final byte[] changeNormDN = getBytes(change.getName().toNormalizedString()); |
| | | |
| | | final DecodeException de = |
| | | change.accept(new ChangeRecordVisitor<DecodeException, Void>() { |
| | |
| | | @Override |
| | | public DecodeException visitChangeRecord(final Void p, |
| | | final AddRequest change) { |
| | | final Entry existingEntry = entries.get(change.getName()); |
| | | if (existingEntry != null) { |
| | | |
| | | if (entries.get(changeNormDN) != null) { |
| | | final Entry existingEntry = decodeEntry(entries.get(changeNormDN)); |
| | | try { |
| | | final Entry entry = |
| | | listener.handleDuplicateEntry(change, existingEntry); |
| | | entries.put(entry.getName(), entry); |
| | | entries.put(getBytes(entry.getName().toNormalizedString()), |
| | | encodeEntry(entry)[1]); |
| | | } catch (final DecodeException e) { |
| | | return e; |
| | | } |
| | | } else { |
| | | entries.put(change.getName(), change); |
| | | entries.put(changeNormDN, encodeEntry(change)[1]); |
| | | } |
| | | return null; |
| | | } |
| | |
| | | @Override |
| | | public DecodeException visitChangeRecord(final Void p, |
| | | final DeleteRequest change) { |
| | | if (!entries.containsKey(change.getName())) { |
| | | if (entries.get(changeNormDN) == null) { |
| | | try { |
| | | listener.handleRejectedChangeRecord(change, |
| | | REJECTED_CHANGE_FAIL_DELETE.get(change.getName() |
| | |
| | | try { |
| | | if (change.getControl(SubtreeDeleteRequestControl.DECODER, |
| | | new DecodeOptions()) != null) { |
| | | entries.subMap(change.getName(), |
| | | change.getName().child(RDN.maxValue())).clear(); |
| | | entries.subMap( |
| | | getBytes(change.getName().toNormalizedString()), |
| | | getBytes(change.getName().child(RDN.maxValue()) |
| | | .toNormalizedString())).clear(); |
| | | } else { |
| | | entries.remove(change.getName()); |
| | | entries.remove(changeNormDN); |
| | | } |
| | | } catch (final DecodeException e) { |
| | | return e; |
| | |
| | | @Override |
| | | public DecodeException visitChangeRecord(final Void p, |
| | | final ModifyDNRequest change) { |
| | | if (!entries.containsKey(change.getName())) { |
| | | if (entries.get(changeNormDN) == null) { |
| | | try { |
| | | listener.handleRejectedChangeRecord(change, |
| | | REJECTED_CHANGE_FAIL_MODIFYDN.get(change.getName() |
| | |
| | | } |
| | | } else { |
| | | // Calculate the old and new DN. |
| | | final DN oldDN = change.getName(); |
| | | final DN oldDN = changeDN; |
| | | |
| | | DN newSuperior = change.getNewSuperior(); |
| | | if (newSuperior == null) { |
| | |
| | | final DN newDN = newSuperior.child(change.getNewRDN()); |
| | | |
| | | // Move the renamed entries into a separate map |
| | | // in order to |
| | | // avoid cases where the renamed subtree |
| | | // overlaps. |
| | | final SortedMap<DN, Entry> renamedEntries = |
| | | new TreeMap<DN, Entry>(); |
| | | final Iterator<Map.Entry<DN, Entry>> i = |
| | | entries.subMap(change.getName(), |
| | | change.getName().child(RDN.maxValue())).entrySet() |
| | | .iterator(); |
| | | while (i.hasNext()) { |
| | | final Map.Entry<DN, Entry> e = i.next(); |
| | | i.remove(); |
| | | // in order to avoid cases where the renamed subtree overlaps. |
| | | final SortedMap<byte[], byte[]> renamedEntries = |
| | | new TreeMap<byte[], byte[]>(DN_ORDER); |
| | | |
| | | final DN renamedDN = e.getKey().rename(oldDN, newDN); |
| | | final Entry entry = e.getValue().setName(renamedDN); |
| | | renamedEntries.put(renamedDN, entry); |
| | | // @formatter:off |
| | | final Iterator<Map.Entry<byte[], byte[]>> i = |
| | | entries.subMap(changeNormDN, |
| | | getBytes((changeDN.child(RDN.maxValue())). |
| | | toNormalizedString())).entrySet().iterator(); |
| | | // @formatter:on |
| | | |
| | | while (i.hasNext()) { |
| | | final Map.Entry<byte[], byte[]> e = i.next(); |
| | | final Entry entry = decodeEntry(e.getValue()); |
| | | final DN renamedDN = entry.getName().rename(oldDN, newDN); |
| | | entry.setName(renamedDN); |
| | | renamedEntries.put(getBytes(renamedDN.toNormalizedString()), |
| | | encodeEntry(entry)[1]); |
| | | i.remove(); |
| | | } |
| | | |
| | | // Modify the target entry. |
| | | final Entry entry = entries.values().iterator().next(); |
| | | // Modify target entry |
| | | final Entry targetEntry = |
| | | decodeEntry(renamedEntries.values().iterator().next()); |
| | | |
| | | if (change.isDeleteOldRDN()) { |
| | | for (final AVA ava : oldDN.rdn()) { |
| | | entry.removeAttribute(ava.toAttribute(), null); |
| | | targetEntry.removeAttribute(ava.toAttribute(), null); |
| | | } |
| | | } |
| | | for (final AVA ava : newDN.rdn()) { |
| | | entry.addAttribute(ava.toAttribute()); |
| | | targetEntry.addAttribute(ava.toAttribute()); |
| | | } |
| | | |
| | | renamedEntries.remove(getBytes(targetEntry.getName() |
| | | .toNormalizedString())); |
| | | renamedEntries.put(getBytes(targetEntry.getName() |
| | | .toNormalizedString()), encodeEntry(targetEntry)[1]); |
| | | |
| | | // Add the renamed entries. |
| | | for (final Entry renamedEntry : renamedEntries.values()) { |
| | | final Entry existingEntry = entries.get(renamedEntry.getName()); |
| | | if (existingEntry != null) { |
| | | final Iterator<byte[]> j = renamedEntries.values().iterator(); |
| | | while (j.hasNext()) { |
| | | final Entry renamedEntry = decodeEntry(j.next()); |
| | | final byte[] existingEntryDn = |
| | | entries.get(getBytes(renamedEntry.getName() |
| | | .toNormalizedString())); |
| | | |
| | | if (existingEntryDn != null) { |
| | | final Entry existingEntry = decodeEntry(existingEntryDn); |
| | | try { |
| | | final Entry tmp = |
| | | listener.handleDuplicateEntry(change, |
| | | existingEntry, renamedEntry); |
| | | entries.put(tmp.getName(), tmp); |
| | | entries.put( |
| | | getBytes(tmp.getName().toNormalizedString()), |
| | | encodeEntry(tmp)[1]); |
| | | } catch (final DecodeException e) { |
| | | return e; |
| | | } |
| | | } else { |
| | | entries.put(renamedEntry.getName(), renamedEntry); |
| | | entries.put(getBytes(renamedEntry.getName() |
| | | .toNormalizedString()), |
| | | encodeEntry(renamedEntry)[1]); |
| | | } |
| | | } |
| | | renamedEntries.clear(); |
| | | } |
| | | return null; |
| | | } |
| | |
| | | @Override |
| | | public DecodeException visitChangeRecord(final Void p, |
| | | final ModifyRequest change) { |
| | | if (!entries.containsKey(change.getName())) { |
| | | if (entries.get(changeNormDN) == null) { |
| | | try { |
| | | listener.handleRejectedChangeRecord(change, |
| | | REJECTED_CHANGE_FAIL_MODIFY.get(change.getName() |
| | |
| | | return e; |
| | | } |
| | | } else { |
| | | final Entry entry = entries.get(change.getName()); |
| | | final Entry entry = decodeEntry(entries.get(changeNormDN)); |
| | | for (final Modification modification : change.getModifications()) { |
| | | final ModificationType modType = |
| | | modification.getModificationType(); |
| | |
| | | + "\": modification type not supported"); |
| | | } |
| | | } |
| | | entries.put(changeNormDN, encodeEntry(entry)[1]); |
| | | } |
| | | return null; |
| | | } |
| | |
| | | } |
| | | |
| | | return new EntryReader() { |
| | | private final Iterator<Entry> iterator = entries.values().iterator(); |
| | | private final Iterator<byte[]> iterator = entries.values().iterator(); |
| | | |
| | | @Override |
| | | public void close() throws IOException { |
| | |
| | | |
| | | @Override |
| | | public Entry readEntry() throws IOException { |
| | | return iterator.next(); |
| | | return decodeEntry(iterator.next()); |
| | | } |
| | | }; |
| | | } |
| | |
| | | }; |
| | | } |
| | | |
| | | private static SortedMap<DN, Entry> readEntries(final EntryReader reader) throws IOException { |
| | | final SortedMap<DN, Entry> entries = new TreeMap<DN, Entry>(); |
| | | private static List<byte[][]> readEntriesAsList(final EntryReader reader) throws IOException { |
| | | final List<byte[][]> entries = new ArrayList<byte[][]>(); |
| | | |
| | | while (reader.hasNext()) { |
| | | final Entry entry = reader.readEntry(); |
| | | entries.put(entry.getName(), entry); |
| | | entries.add(encodeEntry(entry)); |
| | | } |
| | | // Sorting the list by DN |
| | | Collections.sort(entries, DN_ORDER2); |
| | | |
| | | return entries; |
| | | } |
| | | |
| | | private static TreeMap<byte[], byte[]> readEntriesAsMap(final EntryReader reader) |
| | | throws IOException { |
| | | final TreeMap<byte[], byte[]> entries = new TreeMap<byte[], byte[]>(DN_ORDER); |
| | | |
| | | while (reader.hasNext()) { |
| | | final Entry entry = reader.readEntry(); |
| | | final byte[][] bEntry = encodeEntry(entry); |
| | | entries.put(bEntry[0], bEntry[1]); |
| | | } |
| | | |
| | | return entries; |
| | | } |
| | | |
| | | private static SearchResultEntry decodeEntry(final byte[] asn1EntryFormat) { |
| | | final ASN1Reader readerASN1 = ASN1.getReader(asn1EntryFormat); |
| | | try { |
| | | final SearchResultEntry sr = |
| | | LDAPUtils.decodeSearchResultEntry(readerASN1, new DecodeOptions()); |
| | | readerASN1.close(); |
| | | return sr; |
| | | } catch (IOException ex) { |
| | | throw new IllegalStateException(ex); |
| | | } |
| | | } |
| | | |
| | | private static byte[][] encodeEntry(final Entry entry) { |
| | | final byte[][] bEntry = new byte[2][]; |
| | | |
| | | final ByteStringBuilder bsb = new ByteStringBuilder(); |
| | | final ASN1Writer writer = ASN1.getWriter(bsb); |
| | | // Store normalized DN |
| | | bEntry[0] = getBytes(entry.getName().toNormalizedString()); |
| | | try { |
| | | // Store ASN1 representation of the entry. |
| | | LDAPUtils.encodeSearchResultEntry(writer, Responses.newSearchResultEntry(entry)); |
| | | bEntry[1] = bsb.toByteArray(); |
| | | return bEntry; |
| | | } catch (final IOException ioe) { |
| | | throw new IllegalStateException(ioe); |
| | | } |
| | | } |
| | | |
| | | // Prevent instantiation. |
| | | private LDIF() { |
| | | // Do nothing. |
| | |
| | | |
| | | import static org.fest.assertions.Assertions.assertThat; |
| | | |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Iterator; |
| | |
| | | |
| | | // @formatter:off |
| | | final EntryReader reader = new LDIFEntryReader( |
| | | "dn: uid=user.0,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "objectClass: inetorgperson", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: top", |
| | | "uid: user.0" |
| | | "dn: uid=user.0,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "objectClass: inetorgperson", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: top", |
| | | "uid: user.0" |
| | | ); |
| | | // @formatter:on |
| | | |
| | |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | @Test(expectedExceptions = NoSuchElementException.class) |
| | | public final void testLdifSearchWithSchemaMatchFullAttributesTypeOnly() throws Exception { |
| | | |
| | | // @formatter:off |
| | |
| | | assertThat(entry.getAttribute("uid")).isNotNull(); |
| | | assertThat(entry.getAttribute("uid").getAttributeDescription()).isNotNull(); |
| | | assertThat(entry.getAttribute("uid")).isEmpty(); |
| | | |
| | | try { |
| | | assertThat(entry.getAttribute("uid").firstValueAsString()).isNull(); |
| | | } catch (NoSuchElementException ex) { |
| | | // No values, only type. |
| | | // Expected exception on entry.getAttribute("uid").firstValueAsString() |
| | | } |
| | | // The following assert throws an exception because no values contained in, only type. |
| | | assertThat(entry.getAttribute("uid").firstValueAsString()).isNull(); |
| | | } |
| | | resultReader.close(); |
| | | } |
| | |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | @Test(expectedExceptions = NoSuchElementException.class) |
| | | public final void testLdifSearchWithSchemaMatchSpecifiedAttributeTypeOnly() throws Exception { |
| | | |
| | | // @formatter:off |
| | |
| | | assertThat(entry.getAttributeCount()).isEqualTo(1); |
| | | assertThat(entry.getAttribute("uid").getAttributeDescription()).isNotNull(); |
| | | assertThat(entry.getAttribute("uid")).isEmpty(); |
| | | try { |
| | | assertThat(entry.getAttribute("uid").firstValueAsString()).isNull(); |
| | | } catch (NoSuchElementException ex) { |
| | | // No values, only type. |
| | | // Expected exception on entry.getAttribute("uid").firstValueAsString() |
| | | } |
| | | // The following assert throws an exception because no values contained in, only type. |
| | | assertThat(entry.getAttribute("uid").firstValueAsString()).isNull(); |
| | | |
| | | } |
| | | resultReader.close(); |
| | | } |
| | |
| | | "objectClass: person", |
| | | "objectClass: inetorgperson" |
| | | ); |
| | | final Entry e1 = new LinkedHashMapEntry("dn: uid=user.1,ou=People,dc=example,dc=com", "objectClass: person"); |
| | | final Entry e1 = new LinkedHashMapEntry( |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: person" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final SortedMap<DN, Entry> sourceEntries = new TreeMap<DN, Entry>(); |
| | |
| | | final Iterator<Entry> sourceIterator = sourceEntries.values().iterator(); |
| | | |
| | | final EntryReader resultReader = LDIF.newEntryIteratorReader(sourceIterator); |
| | | Entry entry = null; |
| | | int cCount = 0; |
| | | while (resultReader.hasNext()) { |
| | | entry = resultReader.readEntry(); |
| | | final Entry entry = resultReader.readEntry(); |
| | | assertThat(entry.getName().toString()).isNotNull(); |
| | | assertThat(entry.getName().toString()).contains("ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isGreaterThanOrEqualTo(1); |
| | |
| | | assertThat(cr).isInstanceOf(ModifyRequest.class); |
| | | |
| | | // @formatter:off |
| | | /* Expected : 2 add / 1 delete. |
| | | /* Expected : 2 add / 1 delete - output : |
| | | * dn: uid=newuser,ou=People,dc=example,dc=com |
| | | * changetype: modify |
| | | * add: userPassword |
| | |
| | | } |
| | | |
| | | /** |
| | | * Differences between two short ldif examples. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifDiffEntriesShortExamples() throws Exception { |
| | | |
| | | // @formatter:off |
| | | final LDIFEntryReader source = new LDIFEntryReader( |
| | | "dn: uid=user.0,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaccf", |
| | | "sn: Amar", |
| | | "cn: Aaccf Amar", |
| | | "initials: APA", |
| | | "employeeNumber: 0", |
| | | "uid: user.0", |
| | | "mail: user.0@example.com", |
| | | "description: This is the description for Aaccf Amar.", |
| | | "", |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaren", |
| | | "sn: Atp", |
| | | "cn: Aaren Atp", |
| | | "initials: AFA", |
| | | "employeeNumber: 1", |
| | | "uid: user.1", |
| | | "mail: user.1@example.com", |
| | | "description: This is the description for Aaren Atp.", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco", |
| | | "initials: AVA", |
| | | "employeeNumber: 2", |
| | | "uid: user.2", |
| | | "mail: user.2@example.com", |
| | | "description: This is the description for Aarika Atpco.", |
| | | "", |
| | | "dn: uid=user.3,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaron", |
| | | "sn: Atrc", |
| | | "cn: Aaron Atrc", |
| | | "initials: ATA", |
| | | "employeeNumber: 3", |
| | | "uid: user.3", |
| | | "mail: user.3@example.com", |
| | | "description: This is the description for Aaron Atrc.", |
| | | "", |
| | | "dn: uid=user.4,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aartjan", |
| | | "sn: Aalders", |
| | | "cn: Aartjan Aalders", |
| | | "initials: AAA", |
| | | "employeeNumber: 4", |
| | | "uid: user.4", |
| | | "mail: user.4@example.com", |
| | | "description: This is the description for Aartjan Aalders." |
| | | ); |
| | | |
| | | final LDIFEntryReader target = new LDIFEntryReader( |
| | | "dn: uid=user.0,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Amar", // diff |
| | | "sn: Amar", |
| | | "cn: Aaccf Amar", |
| | | "initials: APA", |
| | | "employeeNumber: 55", // diff |
| | | "uid: user.0", |
| | | "mail: user.0@example.com", |
| | | "description: This is the description for Aaccf Amar.", |
| | | "work-phone: 650/506-0666", // diff |
| | | "", |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaren", |
| | | "sn: Atp", |
| | | "cn: Aaren Atp", |
| | | "initials: AFA", |
| | | "employeeNumber: 1", |
| | | "uid: user.1", |
| | | "mail: aaren@example.com", // diff |
| | | "description: This is the description for Aaren Atp.", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco", |
| | | "initials: AVA", |
| | | "employeeNumber: 2", |
| | | "uid: user.2", |
| | | "mail: user.2@example.com", // diff (delete description) |
| | | "", |
| | | "dn: uid=user.3,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaron", |
| | | "sn: Atrc", |
| | | "cn: Aaron Atrc", |
| | | "initials: ATA", |
| | | "employeeNumber: 3", |
| | | "uid: user.999", // diff |
| | | "mail: user.999@example.com", // diff |
| | | "description: This is the description for Aaron Atrc.", |
| | | "", |
| | | "dn: uid=user.4,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aartjan", |
| | | "sn: Aalders", |
| | | "cn: Aartjan Aalders", |
| | | "initials: AAA", |
| | | "employeeNumber: 4", |
| | | "uid: user.4", |
| | | "mail: user.4@example.com", |
| | | "description: This is the description for Aartjan Aalders." |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final ChangeRecordReader reader = LDIF.diff(source, target); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | ChangeRecord cr = reader.readChangeRecord(); |
| | | assertThat(cr.getName().toString()).isEqualTo("uid=user.0,ou=People,dc=example,dc=com"); |
| | | assertThat(cr instanceof ModifyRequest); |
| | | assertThat(((ModifyRequest) cr).getModifications()).isNotEmpty(); |
| | | // 1st entry : 2 add/delete + 1 add(work-phone) |
| | | assertThat(((ModifyRequest) cr).getModifications().size()).isEqualTo(5); |
| | | // 2nd entry : 1 add/delete |
| | | cr = reader.readChangeRecord(); |
| | | assertThat(cr.getName().toString()).isEqualTo("uid=user.1,ou=People,dc=example,dc=com"); |
| | | assertThat(cr instanceof ModifyRequest); |
| | | assertThat(((ModifyRequest) cr).getModifications().size()).isEqualTo(2); |
| | | // 3rd entry : 1 delete |
| | | cr = reader.readChangeRecord(); |
| | | assertThat(cr.getName().toString()).isEqualTo("uid=user.2,ou=People,dc=example,dc=com"); |
| | | assertThat(cr instanceof ModifyRequest); |
| | | assertThat(((ModifyRequest) cr).getModifications().size()).isEqualTo(1); |
| | | assertThat(((ModifyRequest) cr).getModifications().get(0).getModificationType().toString()) |
| | | .isEqualTo("delete"); |
| | | assertThat( |
| | | ((ModifyRequest) cr).getModifications().get(0).getAttribute() |
| | | .getAttributeDescriptionAsString()).isEqualTo("description"); |
| | | // 4th entry : 2 add/delete |
| | | cr = reader.readChangeRecord(); |
| | | assertThat(cr.getName().toString()).isEqualTo("uid=user.3,ou=People,dc=example,dc=com"); |
| | | assertThat(cr instanceof ModifyRequest); |
| | | assertThat(((ModifyRequest) cr).getModifications().size()).isEqualTo(4); |
| | | // 5th entry : 0 modifications |
| | | cr = reader.readChangeRecord(); |
| | | assertThat(cr.getName().toString()).isEqualTo("uid=user.4,ou=People,dc=example,dc=com"); |
| | | assertThat(cr instanceof ModifyRequest); |
| | | assertThat(((ModifyRequest) cr).getModifications().size()).isEqualTo(0); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | |
| | | reader.close(); |
| | | target.close(); |
| | | } |
| | | |
| | | /** |
| | | * Diff between two same entries : no modifications expected. |
| | | * |
| | | * @throws Exception |
| | |
| | | } |
| | | |
| | | /** |
| | | * Test the patch function. Apply simple patch to replace/add data to the |
| | | * input. |
| | | * Create a patch without any differences with the original. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatch() throws Exception { |
| | | public final void testLdifPatchAddNoDiff() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: add", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(3); // objectclass - sn - mail |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * The patch add successfully an attribute 'manager' to the entry. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchAddDiff() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: add", |
| | | "add: manager", |
| | | "manager: uid=joneill,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); // objectclass - sn - mail |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * The patch add two new entries to the original. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchAddDiffNewEntry() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=joneill,ou=People,dc=example,dc=com", |
| | | "changetype: add", |
| | | "add: manager", |
| | | "manager: uid=hamond,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "", |
| | | "dn: uid=djackson,ou=People,dc=example,dc=com", |
| | | "changetype: add", |
| | | "add: manager", |
| | | "manager: uid=joneill,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()) |
| | | .isEqualTo("uid=djackson,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=joneill,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(3); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Try to modify an nonexistent entry. The patch throw an error via the |
| | | * listener which is in RejectedChangeRecordListener.OVERWRITE. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchAddModifyNonExistantEntryDoNothing() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: cn=Lisa Jangles,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "add: telephonenumber", |
| | | "telephonenumber: (408) 555-2468" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(3); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Testing to delete in entry. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchDeleteEntry() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: delete" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Testing to delete in entry. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchDeleteEntryAmongSeveral() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco", |
| | | "uid: user.1", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Eniko", |
| | | "sn: Eniko", |
| | | "cn: Eniko Atpco", |
| | | "uid: user.2", |
| | | "", |
| | | "dn: uid=user.3,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaron", |
| | | "sn: Atrc", |
| | | "cn: Aaron Atrc", |
| | | "uid: user.3" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "changetype: delete" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.1,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.3,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Testing to delete attributes in an entry. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchDeleteAttributesEntry() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Carter", |
| | | "sn: Sam", |
| | | "cn: Sam Carter", |
| | | "uid: scarter", |
| | | "mail: user.1@mail.com", |
| | | "postalAdress: 42 Shepherd Street", |
| | | "work-phone: 650/506-7000", |
| | | "work-phone: 650/506-0666", |
| | | "home-fax: 650-7001" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "delete: work-phone", |
| | | "work-phone: 650/506-0666", |
| | | "-", |
| | | "delete: home-fax" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(8); |
| | | assertThat(entry.getAttribute("work-phone").firstValueAsString()).isEqualTo("650/506-7000"); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Modifying an entry : add |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchModifyEntry() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "add: work-phone", |
| | | "work-phone: 650/506-7000" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * The patch attempts to modify the dn adding uppercase. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchModifyDNEntryUppercaseUid() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "uid: scarter", |
| | | "", |
| | | "dn: uid=djackson,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "uid: djackson" |
| | | |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: modrdn", |
| | | "newrdn: uid=Scarter", |
| | | "deleteoldrdn: 1" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | // does not work with a single entry && ... |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()) |
| | | .isEqualTo("uid=djackson,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=Scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); //The patch create uid attribute on the selected entry. |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Attemp to modify the entry adding uppercase in cn. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchModifyDNEntryUpperCaseDnNameSurname() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: cn=sam carter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "uid: scarter", |
| | | "", |
| | | "dn: uid=djackson,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "uid: djackson" |
| | | |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: cn=sam carter,ou=People,dc=example,dc=com", |
| | | "changetype: modrdn", |
| | | "newrdn: cn=Sam Carter", |
| | | "deleteoldrdn: 1" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | // does not work with a single entry && ... |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "cn=Sam Carter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()) |
| | | .isEqualTo("uid=djackson,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); //The patch create uid attribute on the selected entry. |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * The patch attempts to modify a rdn of a specific entry. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchModifyDNEntry() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "uid: scarter", |
| | | "", |
| | | "dn: uid=djackson,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "uid: djackson" |
| | | |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: modrdn", |
| | | "newrdn: uid=Susan Jacobs", |
| | | "deleteoldrdn: 1" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | // does not work with a single entry && ... |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()) |
| | | .isEqualTo("uid=djackson,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "uid=Susan Jacobs,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); //The patch create uid attribute on the selected entry. |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | @Test() |
| | | public final void testLdifPatchModifyDnEntry2() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco", |
| | | "uid: user.1", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Eniko", |
| | | "sn: Eniko", |
| | | "cn: Eniko Atpco", |
| | | "uid: user.2", |
| | | "", |
| | | "dn: uid=user.3,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaron", |
| | | "sn: Atrc", |
| | | "cn: Aaron Atrc", |
| | | "uid: user.3" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "changetype: modrdn", |
| | | "newrdn: uid=user.22", |
| | | "deleteoldrdn: 1" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.1,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.22,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.3,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Rename a branch : from ou=People,dc=example,dc=com to ou=Human |
| | | * Resources,dc=example,dc=com. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchModifyDnEntryBranch() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: organizationalunit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco", |
| | | "uid: user.1", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Eniko", |
| | | "sn: Eniko", |
| | | "cn: Eniko Atpco", |
| | | "uid: user.2", |
| | | "", |
| | | "dn: uid=user.3,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaron", |
| | | "sn: Atrc", |
| | | "cn: Aaron Atrc", |
| | | "uid: user.3", |
| | | "", |
| | | "dn: uid=user.4,ou=People,dc=example,dc=org", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Allan", |
| | | "sn: Zorg", |
| | | "cn: Allan Zorg", |
| | | "uid: user.4" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: ou=People,dc=example,dc=com", |
| | | "changetype: modrdn", |
| | | "newrdn: ou=Human Resources,dc=example,dc=com", |
| | | "deleteoldrdn: 1" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("ou=Human Resources,dc=example,dc=com"); |
| | | assertThat(entry.getAllAttributes("ou").iterator().next().firstValueAsString()).isEqualTo( |
| | | "Human Resources"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(2); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "uid=user.1,ou=Human Resources,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "uid=user.2,ou=Human Resources,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "uid=user.3,ou=Human Resources,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.4,ou=People,dc=example,dc=org"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Rename a branch : from ou=People,dc=example,dc=com to ou=Human |
| | | * Resources,dc=example,dc=com. In this example deleteoldrdn is set to 0. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchModifyDnEntryBranchKeepsOldRdn() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: organizationalunit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco", |
| | | "uid: user.1", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Eniko", |
| | | "sn: Eniko", |
| | | "cn: Eniko Atpco", |
| | | "uid: user.2", |
| | | "", |
| | | "dn: uid=user.3,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaron", |
| | | "sn: Atrc", |
| | | "cn: Aaron Atrc", |
| | | "uid: user.3", |
| | | "", |
| | | "dn: uid=user.4,ou=People,dc=example,dc=org", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Allan", |
| | | "sn: Zorg", |
| | | "cn: Allan Zorg", |
| | | "uid: user.4" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: ou=People,dc=example,dc=com", |
| | | "changetype: modrdn", |
| | | "newrdn: ou=Human Resources,dc=example,dc=com", |
| | | "deleteoldrdn: 0" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("ou=Human Resources,dc=example,dc=com"); |
| | | assertThat(entry.getAllAttributes("ou").iterator().next().firstValueAsString()).isEqualTo( |
| | | "People"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(2); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "uid=user.1,ou=Human Resources,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "uid=user.2,ou=Human Resources,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "uid=user.3,ou=Human Resources,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.4,ou=People,dc=example,dc=org"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Moves an entry. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchModifyDnEntryNewSuperior() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco", |
| | | "uid: user.1", |
| | | "mail: user.1@mail.com", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Eniko", |
| | | "sn: Eniko", |
| | | "cn: Eniko Atpco", |
| | | "uid: user.2" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "# moves the entry from ou=People, dc=example,dc=com to Marketing", |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "changetype: modrdn", |
| | | "newrdn: uid=user.1", |
| | | "deleteoldrdn: 1", |
| | | "newsuperior: ou=Marketing,dc=example,dc=com" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo( |
| | | "uid=user.1,ou=Marketing,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(6); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.2,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Apply simple patch to replace/add data to the input. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchAddReplace() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "replace:sn", |
| | | "sn: scarter", |
| | | "-", |
| | | "add: manager", |
| | | "manager: uid=joneill,ou=People,dc=example,dc=com" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); // objectclass - sn - mail - manager |
| | | assertThat(entry.getAttribute("manager").firstValueAsString()).isEqualTo( |
| | | "uid=joneill,ou=People,dc=example,dc=com"); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Replace / add postalAdress. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchAddReplaceLanguageTagExample() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "postalAdress;lang-en: Shepherd Street" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "replace: postalAdress;lang-fr", |
| | | "postalAdress;lang-fr: 355 avenue Leon Blum", |
| | | "-", |
| | | "replace: postalAdress;lang-en", |
| | | "postalAdress;lang-en: 42 Shepherd Street" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); // objectclass - sn - mail - manager - postalAdress |
| | | assertThat(entry.getAttribute("postalAdress;lang-fr").firstValueAsString()).isEqualTo( |
| | | "355 avenue Leon Blum"); |
| | | assertThat(entry.getAttribute("postalAdress;lang-en").firstValueAsString()).isEqualTo( |
| | | "42 Shepherd Street"); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Test some changes : add/replace/delete... |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchVariousChanges() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "", |
| | | "dn: uid=user.0,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaccf", |
| | | "sn: Amar", |
| | | "cn: Aaccf Amar", |
| | | "", |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaren", |
| | | "sn: Atp", |
| | | "cn: Aaren Atp", |
| | | "mail: AarenAtp@mail.org", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco", |
| | | "description:: ZnVubnkgZGVzY3JpcHRpb24gISA6RA==", |
| | | "mail:: QWFyaWthQXRwY29AbWFpbC5vcmc=", |
| | | "", |
| | | "dn: uid=user.3,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Kadja", |
| | | "sn: Atpcol", |
| | | "cn: Kadja Atpcol" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final File file = File.createTempFile("sdk", ".png"); |
| | | final String url = file.toURI().toURL().toString(); |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "replace:sn", |
| | | "sn: scarter", |
| | | "-", |
| | | "add: manager", |
| | | "manager: uid=joneill,ou=People,dc=example,dc=com", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "replace:description", |
| | | "description:: QWFyaWthIEF0cGNvIGRlc2NyaXB0aW9uIDogbG9yZW0gaXBzdW0uLi4=", |
| | | "-", |
| | | "add: jpegphoto", |
| | | "jpegphoto:< " + url, |
| | | "", |
| | | "dn: uid=user.3,ou=People,dc=example,dc=com", |
| | | "changetype: delete" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); |
| | | assertThat(entry.getAttribute("manager").firstValueAsString()).isEqualTo( |
| | | "uid=joneill,ou=People,dc=example,dc=com"); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.0,ou=People,dc=example,dc=com"); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(5); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.1,ou=People,dc=example,dc=com"); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(7); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.2,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttribute("mail").firstValueAsString()).isEqualTo( |
| | | "AarikaAtpco@mail.org"); |
| | | assertThat(entry.getAttribute("description").firstValueAsString()).isEqualTo( |
| | | "Aarika Atpco description : lorem ipsum..."); |
| | | assertThat(entry.getAttribute("jpegphoto")).isNotEmpty(); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | |
| | | file.delete(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * An example for illustrate an LDIFChangeRecordReader containing changes on |
| | | * previous ldif. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @Test() |
| | | public final void testLdifPatchContainingChanges() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org", |
| | | "", |
| | | "dn: uid=user.0,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaccf", |
| | | "sn: Amar", |
| | | "cn: Aaccf Amar", |
| | | "", |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aaren", |
| | | "sn: Atp", |
| | | "cn: Aaren Atp", |
| | | "", |
| | | "dn: uid=user.2,ou=People,dc=example,dc=com", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalperson", |
| | | "objectClass: inetorgperson", |
| | | "givenName: Aarika", |
| | | "sn: Atpco", |
| | | "cn: Aarika Atpco" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | |
| | | "sn: scarter", |
| | | "-", |
| | | "add: manager", |
| | | "manager: uid=joneill,ou=People,dc=example,dc=com" |
| | | "manager: uid=joneill,ou=People,dc=example,dc=com", |
| | | "", |
| | | "dn: uid=user.0,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "replace:sn", |
| | | "sn: Amarr", |
| | | "-", |
| | | "delete: givenName", |
| | | "", |
| | | "dn: uid=user.1,ou=People,dc=example,dc=com", |
| | | "changetype: modify", |
| | | "replace:givenName", |
| | | "givenName: Aarwen", |
| | | "-", |
| | | "add: manager", |
| | | "manager: uid=joneill,ou=People,dc=example,dc=com", |
| | | "-", |
| | | "add: mail", |
| | | "mail: Aarwen@mail.com", |
| | | "-", |
| | | "add: fax", |
| | | "fax: 555 555-5555", |
| | | "-", |
| | | "add: description", |
| | | "description:: QWFyd2VuIGRlc2NyaXB0aW9uLg==" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:on |
| | | final EntryReader reader = LDIF.patch(input, patch); |
| | | |
| | | Entry entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=scarter,ou=People,dc=example,dc=com"); |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); // objectclass - sn - mail - manager |
| | | // Attr. list : objectclass - sn - mail - manager |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); |
| | | assertThat(entry.getAttribute("manager").firstValueAsString()).isEqualTo( |
| | | "uid=joneill,ou=People,dc=example,dc=com"); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | // Attr. list : objectclass - sn - cn |
| | | assertThat(entry.getAttributeCount()).isEqualTo(3); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.1,ou=People,dc=example,dc=com"); |
| | | // Attr. list : objectclass - sn - cn - givenName - manager - mail - fax - description |
| | | assertThat(entry.getAttributeCount()).isEqualTo(8); |
| | | assertThat(entry.getAttribute("description").firstValueAsString()).isEqualTo( |
| | | "Aarwen description."); |
| | | assertThat(reader.hasNext()).isTrue(); |
| | | // Last entry, no modification on it. |
| | | entry = reader.readEntry(); |
| | | assertThat(entry.getName().toString()).isEqualTo("uid=user.2,ou=People,dc=example,dc=com"); |
| | | // Attr. list : objectClass - givenname - sn - cn |
| | | assertThat(entry.getAttributeCount()).isEqualTo(4); |
| | | assertThat(reader.hasNext()).isFalse(); |
| | | reader.close(); |
| | | } |
| | | |
| | | /** |
| | | * Try to apply a patch which data are not valid. Exception expected. |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | @SuppressWarnings("resource") |
| | | @Test(expectedExceptions = DecodeException.class) |
| | | public final void testLdifPatchInvalidChangeRecord() throws Exception { |
| | | // @formatter:off |
| | | final LDIFEntryReader input = new LDIFEntryReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "objectClass: person", |
| | | "sn: new user", |
| | | "mail: mail@mailme.org" |
| | | ); |
| | | // @formatter:on |
| | | |
| | | // @formatter:off |
| | | final LDIFChangeRecordReader patch = new LDIFChangeRecordReader( |
| | | "dn: uid=scarter,ou=People,dc=example,dc=com", |
| | | "changetype: modif\u0000", |
| | | "replace:sn", |
| | | "sn: scarter", |
| | | "-", |
| | | "add: manager\u0000", |
| | | "manager: uid=joneill,ou=People,dc=example,dc=com" |
| | | ); |
| | | // @formatter:on |
| | | EntryReader reader = new LDIFEntryReader(); |
| | | try { |
| | | reader = LDIF.patch(input, patch); |
| | | reader.readEntry(); |
| | | } finally { |
| | | reader.close(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * LDIF patch - EntryReader/ChangeRecordReader doesn't allow null. Exception |
| | | * expected. |
| | | * |
| | |
| | | public final void testLdifPatchDoesntAllowNull() throws Exception { |
| | | LDIF.patch(null, null); |
| | | } |
| | | |
| | | } |