opendj-sdk/opends/src/server/org/opends/server/tools/LDAPModify.java
@@ -49,6 +49,7 @@ import org.opends.server.protocols.ldap.LDAPException; import org.opends.server.protocols.ldap.LDAPFilter; import org.opends.server.protocols.ldap.LDAPMessage; import org.opends.server.protocols.ldap.LDAPModification; import org.opends.server.protocols.ldap.ModifyRequestProtocolOp; import org.opends.server.protocols.ldap.ModifyResponseProtocolOp; import org.opends.server.protocols.ldap.ModifyDNRequestProtocolOp; @@ -236,7 +237,7 @@ case ADD: operationType = "ADD"; AddChangeRecordEntry addEntry = (AddChangeRecordEntry) entry; ArrayList<Attribute> attrs = addEntry.getAttributes(); List<Attribute> attrs = addEntry.getAttributes(); ArrayList<LDAPAttribute> attributes = new ArrayList<LDAPAttribute>(attrs.size()); for(Attribute a : attrs) @@ -256,8 +257,9 @@ case MODIFY: operationType = "MODIFY"; ModifyChangeRecordEntry modEntry = (ModifyChangeRecordEntry) entry; protocolOp = new ModifyRequestProtocolOp(asn1OctetStr, modEntry.getModifications()); ArrayList<LDAPModification> mods = new ArrayList<LDAPModification>(modEntry.getModifications()); protocolOp = new ModifyRequestProtocolOp(asn1OctetStr, mods); msgID = MSGID_PROCESSING_OPERATION; System.out.println(getMessage(msgID, operationType, asn1OctetStr)); break; opendj-sdk/opends/src/server/org/opends/server/util/AddChangeRecordEntry.java
@@ -32,8 +32,9 @@ import static org.opends.server.loggers.Debug.debugEnter; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Collections; import java.util.List; import java.util.Map; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; @@ -58,28 +59,35 @@ /** * The entry attributes for this operation. */ private HashMap<AttributeType,ArrayList<Attribute>> entryAttributes; private final List<Attribute> attributes; // The LDIF reader instance private LDIFReader reader; /** * Creates a new entry with the provided information. * * @param dn The distinguished name for this entry. * @param reader The LDIF reader instance used to read the entries. * @param dn * The distinguished name for this entry. * @param attributes * The entry attributes for this operation. */ public AddChangeRecordEntry(DN dn, LDIFReader reader) public AddChangeRecordEntry(DN dn, Map<AttributeType,List<Attribute>> attributes) { super(dn, reader); super(dn); assert debugConstructor(CLASS_NAME, String.valueOf(dn), String.valueOf(reader)); String.valueOf(attributes)); this.reader = reader; entryAttributes = new HashMap<AttributeType, ArrayList<Attribute>>(); this.attributes = new ArrayList<Attribute>(attributes.size()); for (List<Attribute> list : attributes.values()) { for (Attribute a : list) { this.attributes.add(a); } } } @@ -97,45 +105,19 @@ } /** * Retrieves the entire set of attributes for this entry. * The caller must not modify the contents of this list. * <p> * The returned list is read-only. * * @return The entire set of attributes for this entry. * @return The entire unmodifiable list of attributes for this entry. */ public ArrayList<Attribute> getAttributes() public List<Attribute> getAttributes() { assert debugEnter(CLASS_NAME, "getAttributes"); ArrayList<Attribute> attributes = new ArrayList<Attribute>(); for (ArrayList<Attribute> list : entryAttributes.values()) { for (Attribute a : list) { attributes.add(a); } } return attributes; } /** * Parse the lines and populate the internal structures. * * @param lines The lines to parse. * @param lineNumber The current line number * * @exception LDIFException if there is an error during parsing. */ public void parse(LinkedList<StringBuilder> lines, long lineNumber) throws LDIFException { assert debugEnter(CLASS_NAME, "parse", String.valueOf(lines), String.valueOf(lineNumber)); for(StringBuilder line : lines) { reader.readAttribute(lines, line, getDN(), entryAttributes); } return Collections.unmodifiableList(attributes); } } opendj-sdk/opends/src/server/org/opends/server/util/ChangeRecordEntry.java
@@ -31,11 +31,7 @@ import static org.opends.server.loggers.Debug.debugConstructor; import static org.opends.server.loggers.Debug.debugEnter; import java.util.ArrayList; import java.util.LinkedList; import org.opends.server.types.DN; import org.opends.server.types.RDN; @@ -58,30 +54,6 @@ /** * Creates a new entry with the provided information. * * @param dn The distinguished name for this entry. * @param reader The LDIF reader. */ protected ChangeRecordEntry(DN dn, LDIFReader reader) { assert debugConstructor(CLASS_NAME, String.valueOf(dn), String.valueOf(reader)); if (dn == null) { this.dn = new DN(new ArrayList<RDN>(0)); } else { this.dn = dn; } } /** * Creates a new change record entry with the provided information. * * @param dn The distinguished name for this change record entry. @@ -116,44 +88,10 @@ /** * Specifies the distinguished name for this entry. * * @param dn The distinguished name for this entry. */ public final void setDN(DN dn) { assert debugEnter(CLASS_NAME, "setDN", String.valueOf(dn)); if (dn == null) { this.dn = new DN(new ArrayList<RDN>(0)); } else { this.dn = dn; } } /** * Retrieves the name of the change operation type. * * @return The name of the change operation type. */ public abstract ChangeOperationType getChangeOperationType(); /** * Parse and populate internal structures from the specified lines. * @param lines The list of lines to parse from. * @param lineNumber The current line number during the parsing. * * @exception LDIFException If there is a parsing error. */ public abstract void parse(LinkedList<StringBuilder> lines, long lineNumber) throws LDIFException; } opendj-sdk/opends/src/server/org/opends/server/util/DeleteChangeRecordEntry.java
@@ -30,16 +30,11 @@ import static org.opends.server.loggers.Debug.debugConstructor; import static org.opends.server.loggers.Debug.debugEnter; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.messages.UtilityMessages.*; import java.util.LinkedList; import org.opends.server.types.DN; /** * This class defines a data structure for a change record entry for * an delete operation. It includes a DN and a set of attributes, as well as @@ -59,14 +54,12 @@ * Creates a new entry with the provided information. * * @param dn The distinguished name for this entry. * @param reader The LDIFReader instance used to read the entries. */ public DeleteChangeRecordEntry(DN dn, LDIFReader reader) public DeleteChangeRecordEntry(DN dn) { super(dn, reader); assert debugConstructor(CLASS_NAME, String.valueOf(dn), String.valueOf(reader)); super(dn); assert debugConstructor(CLASS_NAME, String.valueOf(dn)); } @@ -83,32 +76,5 @@ return ChangeOperationType.DELETE; } /** * Parse the lines and populate the internal structures. * * @param lines The lines to parse. * @param lineNumber The current line number. * * @exception LDIFException if there is an error during parsing. */ public void parse(LinkedList<StringBuilder> lines, long lineNumber) throws LDIFException { assert debugEnter(CLASS_NAME, "parse", String.valueOf(lines), String.valueOf(lineNumber)); if(! lines.isEmpty()) { int msgID = MSGID_LDIF_INVALID_DELETE_ATTRIBUTES; String message = getMessage(msgID); throw new LDIFException(msgID, message, lineNumber, true); } } } opendj-sdk/opends/src/server/org/opends/server/util/LDIFReader.java
@@ -28,11 +28,17 @@ import static org.opends.server.loggers.Debug.*; import static org.opends.server.loggers.Error.logError; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.messages.UtilityMessages.*; import static org.opends.server.util.StaticUtils.toLowerCase; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; @@ -45,25 +51,22 @@ import org.opends.server.core.DirectoryServer; import org.opends.server.core.PluginConfigManager; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.protocols.ldap.LDAPAttribute; import org.opends.server.protocols.ldap.LDAPModification; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.DN; import org.opends.server.types.DebugLogCategory; import org.opends.server.types.DebugLogSeverity; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.ErrorLogCategory; import org.opends.server.types.ErrorLogSeverity; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.ModificationType; import org.opends.server.types.ObjectClass; import org.opends.server.types.RDN; import static org.opends.server.loggers.Debug.*; import static org.opends.server.loggers.Error.*; import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.messages.UtilityMessages.*; import static org.opends.server.util.StaticUtils.*; /** @@ -71,7 +74,7 @@ * provides support for both standard entries and change entries (as would be * used with a tool like ldapmodify). */ public class LDIFReader public final class LDIFReader { /** * The fully-qualified name of this class for debugging purposes. @@ -310,28 +313,7 @@ String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, invalidReason.toString()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readEntry", e); } } logToRejectWriter(lines, message); entriesRejected++; throw new LDIFException(msgID, message, lastEntryLineNumber, true); } @@ -391,19 +373,19 @@ { if(changeType.equals("add")) { entry = new AddChangeRecordEntry(entryDN, this); entry = parseAddChangeRecordEntry(entryDN, lines); } else if (changeType.equals("delete")) { entry = new DeleteChangeRecordEntry(entryDN, this); entry = parseDeleteChangeRecordEntry(entryDN, lines); } else if (changeType.equals("modify")) { entry = new ModifyChangeRecordEntry(entryDN, this); entry = parseModifyChangeRecordEntry(entryDN, lines); } else if (changeType.equals("modrdn")) { entry = new ModifyDNChangeRecordEntry(entryDN, this); entry = parseModifyDNChangeRecordEntry(entryDN, lines); } else if (changeType.equals("moddn")) { entry = new ModifyDNChangeRecordEntry(entryDN, this); entry = parseModifyDNChangeRecordEntry(entryDN, lines); } else { int msgID = MSGID_LDIF_INVALID_CHANGETYPE_ATTRIBUTE; @@ -416,7 +398,7 @@ // default to "add"? if(defaultAdd) { entry = new AddChangeRecordEntry(entryDN, this); entry = parseAddChangeRecordEntry(entryDN, lines); } else { int msgID = MSGID_LDIF_INVALID_CHANGETYPE_ATTRIBUTE; @@ -426,16 +408,12 @@ } } // Parse the lines to populate the change record entry data structures. entry.parse(lines, lastEntryLineNumber); return entry; } } /** * Reads a set of lines from the next entry in the LDIF source. * @@ -512,23 +490,7 @@ { int msgID = MSGID_LDIF_INVALID_LEADING_SPACE; String message = getMessage(msgID, lineNumber, line); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.write(line); rejectWriter.newLine(); rejectWriter.newLine(); } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lineNumber, false); } } @@ -584,26 +546,7 @@ int msgID = MSGID_LDIF_NO_ATTR_NAME; String message = getMessage(msgID, lastEntryLineNumber, line.toString()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readDN", e); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true); } @@ -619,26 +562,7 @@ int msgID = MSGID_LDIF_NO_DN; String message = getMessage(msgID, lastEntryLineNumber, line.toString()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readDN", e); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true); } @@ -679,26 +603,7 @@ String message = getMessage(msgID, lastEntryLineNumber, line, String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readDN", e2); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } @@ -715,26 +620,7 @@ String message = getMessage(msgID, lastEntryLineNumber, line.toString(), de.getErrorMessage()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readDN", e); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, de); } @@ -746,26 +632,7 @@ String message = getMessage(msgID, lastEntryLineNumber, line.toString(), String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readDN", e2); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } @@ -794,26 +661,7 @@ String message = getMessage(msgID, lastEntryLineNumber, line.toString(), de.getErrorMessage()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readDN", e); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, de); } @@ -825,26 +673,7 @@ String message = getMessage(msgID, lastEntryLineNumber, line.toString(), String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readDN", e2); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } @@ -852,6 +681,7 @@ } /** * Reads the changetype of the entry from the provided list of lines. If * there is no changetype attribute then an add is assumed. @@ -882,28 +712,7 @@ { int msgID = MSGID_LDIF_NO_ATTR_NAME; String message = getMessage(msgID, lastEntryLineNumber, line.toString()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readChangeType", e); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true); } @@ -915,7 +724,7 @@ } else { // Remove the line StringBuilder ln = lines.remove(); lines.remove(); } @@ -957,28 +766,7 @@ int msgID = MSGID_LDIF_COULD_NOT_BASE64_DECODE_DN; String message = getMessage(msgID, lastEntryLineNumber, line, String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readChangeType", e2); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } @@ -1027,270 +815,24 @@ HashMap<AttributeType,List<Attribute>> operationalAttributes) throws LDIFException { assert debugEnter(CLASS_NAME, "readAttribute", String.valueOf(line), String.valueOf(entryDN), String.valueOf(objectClasses), String.valueOf(userAttributes), String.valueOf(operationalAttributes)); assert debugEnter(CLASS_NAME, "readAttribute", String.valueOf(line), String.valueOf(entryDN), String.valueOf(objectClasses), String.valueOf(userAttributes), String.valueOf(operationalAttributes)); int colonPos = line.indexOf(":"); if (colonPos <= 0) { int msgID = MSGID_LDIF_NO_ATTR_NAME; String message = getMessage(msgID, lastEntryLineNumber, line.toString()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true); } LinkedHashSet<String> options; String attrName = line.substring(0, colonPos); int semicolonPos = attrName.indexOf(';'); if (semicolonPos > 0) { options = new LinkedHashSet<String>(); int nextPos = attrName.indexOf(';', semicolonPos+1); while (nextPos > 0) { String option = attrName.substring(semicolonPos+1, nextPos); if (option.length() > 0) { options.add(option); semicolonPos = nextPos; nextPos = attrName.indexOf(';', semicolonPos+1); } } String option = attrName.substring(semicolonPos+1); if (option.length() > 0) { options.add(option); } attrName = attrName.substring(0, attrName.indexOf(';')); } else { options = null; } // Parse the attribute type description. int colonPos = parseColonPosition(lines, line); String attrDescr = line.substring(0, colonPos); Attribute attribute = parseAttrDescription(attrDescr); String attrName = attribute.getName(); String lowerName = toLowerCase(attrName); LinkedHashSet<String> options = attribute.getOptions(); // Look at the character immediately after the colon. If there is none, // then assume an attribute with an empty value. If it is another colon, // then the value must be base64-encoded. If it is a less-than sign, then // assume that it is a URL. Otherwise, it is a regular value. int length = line.length(); ASN1OctetString value; if (colonPos == (length-1)) { value = new ASN1OctetString(); } else { char c = line.charAt(colonPos+1); if (c == ':') { // The value is base64-encoded. Find the first non-blank character, // take the rest of the line, and base64-decode it. int pos = colonPos+2; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } try { value = new ASN1OctetString(Base64.decode(line.substring(pos))); } catch (Exception e) { // The value did not have a valid base64-encoding. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_COULD_NOT_BASE64_DECODE_ATTR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, line, String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } } else if (c == '<') { // Find the first non-blank character, decode the rest of the line as a // URL, and read its contents. int pos = colonPos+2; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } URL contentURL; try { contentURL = new URL(line.substring(pos)); } catch (Exception e) { // The URL was malformed or had an invalid protocol. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_INVALID_URL; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, String.valueOf(attrName), String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } InputStream inputStream = null; ByteArrayOutputStream outputStream = null; try { outputStream = new ByteArrayOutputStream(); inputStream = contentURL.openConnection().getInputStream(); int bytesRead; while ((bytesRead = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, bytesRead); } value = new ASN1OctetString(outputStream.toByteArray()); } catch (Exception e) { // We were unable to read the contents of that URL for some reason. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_URL_IO_ERROR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, String.valueOf(attrName), String.valueOf(contentURL), String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } finally { if (outputStream != null) { try { outputStream.close(); } catch (Exception e) {} } if (inputStream != null) { try { inputStream.close(); } catch (Exception e) {} } } } else { // The rest of the line should be the value. Skip over any spaces and // take the rest of the line as the value. int pos = colonPos+1; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } value = new ASN1OctetString(line.substring(pos)); } } // Now parse the attribute value. ASN1OctetString value = parseSingleValue(lines, line, entryDN, colonPos, attrName); // See if this is an objectclass or an attribute. Then get the // corresponding definition and add the value to the appropriate hash. @@ -1348,45 +890,7 @@ } AttributeValue attributeValue; try { attributeValue = new AttributeValue(attrType, value); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_INVALID_ATTR_SYNTAX; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, value.stringValue(), attrName, String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } AttributeValue attributeValue = new AttributeValue(attrType, value); List<Attribute> attrList; if (attrType.isOperational()) { @@ -1433,28 +937,7 @@ String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, attrName, value.stringValue()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true); } else if (attrType.isSingleValue() && (! valueSet.isEmpty())) @@ -1462,28 +945,7 @@ int msgID = MSGID_LDIF_MULTIPLE_VALUES_FOR_SINGLE_VALUED_ATTR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, attrName); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); } } logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true); } else @@ -1506,367 +968,6 @@ } /** * Decodes the provided line as an LDIF attribute and adds it to the * appropriate hash. * * @param lines The full set of lines that comprise the * entry (used for writing reject information). * @param line The line to decode. * @param entryDN The DN of the entry being decoded. * @param entryAttributes The set of attributes decoded so far * for the current entry. * * @throws LDIFException If a problem occurs while trying to decode the * attribute contained in the provided entry. */ public void readAttribute(LinkedList<StringBuilder> lines, StringBuilder line, DN entryDN, HashMap<AttributeType,ArrayList<Attribute>> entryAttributes) throws LDIFException { assert debugEnter(CLASS_NAME, "readAttribute", String.valueOf(line), String.valueOf(entryDN), String.valueOf(entryAttributes)); int colonPos = line.indexOf(":"); if (colonPos <= 0) { int msgID = MSGID_LDIF_NO_ATTR_NAME; String message = getMessage(msgID, lastEntryLineNumber, line.toString()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true); } String attrDescr = line.substring(0, colonPos); Attribute attribute = parseAttrDescription(attrDescr); String attrName = attribute.getName(); LinkedHashSet<String> options = attribute.getOptions(); // Look at the character immediately after the colon. If there is none, // then assume an attribute with an empty value. If it is another colon, // then the value must be base64-encoded. If it is a less-than sign, then // assume that it is a URL. Otherwise, it is a regular value. int length = line.length(); ASN1OctetString value; if (colonPos == (length-1)) { value = new ASN1OctetString(); } else { char c = line.charAt(colonPos+1); if (c == ':') { // The value is base64-encoded. Find the first non-blank character, // take the rest of the line, and base64-decode it. int pos = colonPos+2; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } try { value = new ASN1OctetString(Base64.decode(line.substring(pos))); } catch (Exception e) { // The value did not have a valid base64-encoding. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_COULD_NOT_BASE64_DECODE_ATTR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, line, String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } } else if (c == '<') { // Find the first non-blank character, decode the rest of the line as a // URL, and read its contents. int pos = colonPos+2; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } URL contentURL; try { contentURL = new URL(line.substring(pos)); } catch (Exception e) { // The URL was malformed or had an invalid protocol. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_INVALID_URL; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, String.valueOf(attrName), String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } InputStream inputStream = null; ByteArrayOutputStream outputStream = null; try { outputStream = new ByteArrayOutputStream(); inputStream = contentURL.openConnection().getInputStream(); int bytesRead; while ((bytesRead = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, bytesRead); } value = new ASN1OctetString(outputStream.toByteArray()); } catch (Exception e) { // We were unable to read the contents of that URL for some reason. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_URL_IO_ERROR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, String.valueOf(attrName), String.valueOf(contentURL), String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } finally { if (outputStream != null) { try { outputStream.close(); } catch (Exception e) {} } if (inputStream != null) { try { inputStream.close(); } catch (Exception e) {} } } } else { // The rest of the line should be the value. Skip over any spaces and // take the rest of the line as the value. int pos = colonPos+1; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } value = new ASN1OctetString(line.substring(pos)); } } AttributeType attrType = attribute.getAttributeType(); AttributeValue attributeValue; try { attributeValue = new AttributeValue(attrType, value); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_INVALID_ATTR_SYNTAX; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, value.stringValue(), attrName, String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } ArrayList<Attribute> attrList; attrList = entryAttributes.get(attrType); if (attrList == null) { attribute.getValues().add(attributeValue); attrList = new ArrayList<Attribute>(); attrList.add(attribute); entryAttributes.put(attrType, attrList); return; } // Check to see if any of the attributes in the list have the same set of // options. If so, then try to add a value to that attribute. for (Attribute a : attrList) { if (a.optionsEqual(options)) { LinkedHashSet<AttributeValue> valueSet = a.getValues(); if (valueSet.contains(attributeValue)) { int msgID = MSGID_LDIF_DUPLICATE_ATTR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, attrName, value.stringValue()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true); } else { valueSet.add(attributeValue); return; } } } // No set of matching options was found, so create a new one and add it to // the list. attribute.getValues().add(attributeValue); attrList.add(attribute); return; } /** * Decodes the provided line as an LDIF attribute and returns the @@ -1885,295 +986,36 @@ * entry or if the parsed attribute name does * not match the specified attribute name. */ public Attribute readSingleValueAttribute( private Attribute readSingleValueAttribute( LinkedList<StringBuilder> lines, StringBuilder line, DN entryDN, String attributeName) throws LDIFException { assert debugEnter(CLASS_NAME, "readAttribute", String.valueOf(lines), String.valueOf(line), String.valueOf(entryDN), String.valueOf(attributeName)); assert debugEnter(CLASS_NAME, "readSingleValueAttribute", String.valueOf(lines), String.valueOf(line), String.valueOf(entryDN), String.valueOf(attributeName)); int colonPos = line.indexOf(":"); if (colonPos <= 0) { int msgID = MSGID_LDIF_NO_ATTR_NAME; String message = getMessage(msgID, lastEntryLineNumber, line.toString()); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true); } // Parse the attribute type description. int colonPos = parseColonPosition(lines, line); String attrDescr = line.substring(0, colonPos); Attribute attribute = parseAttrDescription(attrDescr); String attrName = attribute.getName(); String lowerName = toLowerCase(attrName); if(attributeName != null && !attributeName.toLowerCase().equals(lowerName)) if(attributeName != null && !toLowerCase(attributeName).equals(lowerName)) { int msgID = MSGID_LDIF_INVALID_CHANGERECORD_ATTRIBUTE; String message = getMessage(msgID, lowerName, attributeName); throw new LDIFException(msgID, message, lastEntryLineNumber, false); } // Look at the character immediately after the colon. If there is none, // then assume an attribute with an empty value. If it is another colon, // then the value must be base64-encoded. If it is a less-than sign, then // assume that it is a URL. Otherwise, it is a regular value. int length = line.length(); ASN1OctetString value; if (colonPos == (length-1)) { value = new ASN1OctetString(); } else { char c = line.charAt(colonPos+1); if (c == ':') { // The value is base64-encoded. Find the first non-blank character, // take the rest of the line, and base64-decode it. int pos = colonPos+2; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } try { value = new ASN1OctetString(Base64.decode(line.substring(pos))); } catch (Exception e) { // The value did not have a valid base64-encoding. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_COULD_NOT_BASE64_DECODE_ATTR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, line, String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } } else if (c == '<') { // Find the first non-blank character, decode the rest of the line as a // URL, and read its contents. int pos = colonPos+2; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } URL contentURL; try { contentURL = new URL(line.substring(pos)); } catch (Exception e) { // The URL was malformed or had an invalid protocol. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_INVALID_URL; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, String.valueOf(attrName), String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } InputStream inputStream = null; ByteArrayOutputStream outputStream = null; try { outputStream = new ByteArrayOutputStream(); inputStream = contentURL.openConnection().getInputStream(); int bytesRead; while ((bytesRead = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, bytesRead); } value = new ASN1OctetString(outputStream.toByteArray()); } catch (Exception e) { // We were unable to read the contents of that URL for some reason. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_URL_IO_ERROR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, String.valueOf(attrName), String.valueOf(contentURL), String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } finally { if (outputStream != null) { try { outputStream.close(); } catch (Exception e) {} } if (inputStream != null) { try { inputStream.close(); } catch (Exception e) {} } } } else { // The rest of the line should be the value. Skip over any spaces and // take the rest of the line as the value. int pos = colonPos+1; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } value = new ASN1OctetString(line.substring(pos)); } } // Now parse the attribute value. ASN1OctetString value = parseSingleValue(lines, line, entryDN, colonPos, attrName); AttributeType attrType = attribute.getAttributeType(); AttributeValue attributeValue; try { attributeValue = new AttributeValue(attrType, value); } catch (Exception e) { assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_INVALID_ATTR_SYNTAX; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, value.stringValue(), attrName, String.valueOf(e)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# " + message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e2) { assert debugException(CLASS_NAME, "readAttribute", e2); } } throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } AttributeValue attributeValue = new AttributeValue(attrType, value); attribute.getValues().add(attributeValue); return attribute; @@ -2216,7 +1058,8 @@ { try { rejectWriter.write("# " + message); rejectWriter.write("# "); rejectWriter.write(message); rejectWriter.newLine(); for (StringBuilder sb : lastEntryHeaderLines) @@ -2260,7 +1103,7 @@ * @return A new attribute with no values, representing the attribute type * and its options. */ public static Attribute parseAttrDescription(String attrDescr) private static Attribute parseAttrDescription(String attrDescr) { assert debugEnter(CLASS_NAME, "parseAttributeDescription", String.valueOf(attrDescr)); @@ -2354,5 +1197,551 @@ return entriesRejected; } /** * Parse a modifyDN change record entry from LDIF. * * @param entryDN * The name of the entry being modified. * @param lines * The lines to parse. * @return Returns the parsed modifyDN change record entry. * @throws LDIFException * If there was an error when parsing the change record. */ private ChangeRecordEntry parseModifyDNChangeRecordEntry(DN entryDN, LinkedList<StringBuilder> lines) throws LDIFException { assert debugEnter(CLASS_NAME, "parseModifyDNChangeRecordEntry", String.valueOf(entryDN), String.valueOf(lines), String.valueOf(lineNumber)); DN newSuperiorDN = null; RDN newRDN = null; boolean deleteOldRDN = false; if(lines.isEmpty()) { int msgID = MSGID_LDIF_NO_MOD_DN_ATTRIBUTES; String message = getMessage(msgID); throw new LDIFException(msgID, message, lineNumber, true); } StringBuilder line = lines.remove(); String rdnStr = getModifyDNAttributeValue(lines, line, entryDN, "newrdn"); try { newRDN = RDN.decode(rdnStr); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "parse", de); int msgID = MSGID_LDIF_INVALID_DN; String message = getMessage(msgID, lineNumber, line.toString(), de.getErrorMessage()); throw new LDIFException(msgID, message, lineNumber, true); } catch (Exception e) { assert debugException(CLASS_NAME, "parse", e); int msgID = MSGID_LDIF_INVALID_DN; String message = getMessage(msgID, lineNumber, line.toString(), e.getMessage()); throw new LDIFException(msgID, message, lineNumber, true); } if(lines.isEmpty()) { int msgID = MSGID_LDIF_NO_DELETE_OLDRDN_ATTRIBUTE; String message = getMessage(msgID); throw new LDIFException(msgID, message, lineNumber, true); } lineNumber++; line = lines.remove(); String delStr = getModifyDNAttributeValue(lines, line, entryDN, "deleteoldrdn"); if(delStr.equalsIgnoreCase("false") || delStr.equalsIgnoreCase("no") || delStr.equalsIgnoreCase("0")) { deleteOldRDN = false; } else if(delStr.equalsIgnoreCase("true") || delStr.equalsIgnoreCase("yes") || delStr.equalsIgnoreCase("1")) { deleteOldRDN = true; } else { int msgID = MSGID_LDIF_INVALID_DELETE_OLDRDN_ATTRIBUTE; String message = getMessage(msgID, delStr); throw new LDIFException(msgID, message, lineNumber, true); } if(!lines.isEmpty()) { lineNumber++; line = lines.remove(); String dnStr = getModifyDNAttributeValue(lines, line, entryDN, "newsuperior"); try { newSuperiorDN = DN.decode(dnStr); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "parse", de); int msgID = MSGID_LDIF_INVALID_DN; String message = getMessage(msgID, lineNumber, line.toString(), de.getErrorMessage()); throw new LDIFException(msgID, message, lineNumber, true); } catch (Exception e) { assert debugException(CLASS_NAME, "parse", e); int msgID = MSGID_LDIF_INVALID_DN; String message = getMessage(msgID, lineNumber, line.toString(), e.getMessage()); throw new LDIFException(msgID, message, lineNumber, true); } } return new ModifyDNChangeRecordEntry(entryDN, newSuperiorDN, newRDN, deleteOldRDN); } /** * Return the string value for the specified attribute name which only * has one value. * * @param lines * The set of lines for this change record entry. * @param line * The line currently being examined. * @param entryDN * The name of the entry being modified. * @param attributeName * The attribute name * @return the string value for the attribute name. * @throws LDIFException * If a problem occurs while attempting to determine the * attribute value. */ private String getModifyDNAttributeValue(LinkedList<StringBuilder> lines, StringBuilder line, DN entryDN, String attributeName) throws LDIFException { assert debugEnter(CLASS_NAME, "getModifyDNAttributeValue", String.valueOf(lines), String.valueOf(line), String.valueOf(entryDN), String.valueOf(attributeName)); Attribute attr = readSingleValueAttribute(lines, line, entryDN, attributeName); LinkedHashSet<AttributeValue> values = attr.getValues(); // Get the attribute value Object[] vals = values.toArray(); return (((AttributeValue)vals[0]).getStringValue()); } /** * Parse a modify change record entry from LDIF. * * @param entryDN * The name of the entry being modified. * @param lines * The lines to parse. * @return Returns the parsed modify change record entry. * @throws LDIFException * If there was an error when parsing the change record. */ private ChangeRecordEntry parseModifyChangeRecordEntry(DN entryDN, LinkedList<StringBuilder> lines) throws LDIFException { assert debugEnter(CLASS_NAME, "parseModifyChangeRecordEntry", String.valueOf(entryDN), String.valueOf(lines), String.valueOf(lineNumber)); List<LDAPModification> modifications = new ArrayList<LDAPModification>(); while(!lines.isEmpty()) { ModificationType modType = null; StringBuilder line = lines.remove(); Attribute attr = readSingleValueAttribute(lines, line, entryDN, null); String name = attr.getName(); LinkedHashSet<AttributeValue> values = attr.getValues(); // Get the attribute description String attrDescr = values.iterator().next().getStringValue(); String lowerName = toLowerCase(name); if(lowerName.equals("add")) { modType = ModificationType.ADD; } else if(lowerName.equals("delete")) { modType = ModificationType.DELETE; } else if(lowerName.equals("replace")) { modType = ModificationType.REPLACE; } else if(lowerName.equals("increment")) { modType = ModificationType.INCREMENT; } else { // Invalid attribute name. int msgID = MSGID_LDIF_INVALID_MODIFY_ATTRIBUTE; String message = getMessage(msgID, name, "add, delete, replace, increment"); throw new LDIFException(msgID, message, lineNumber, true); } // Now go through the rest of the attributes till the "-" line is // reached. Attribute modAttr = LDIFReader.parseAttrDescription(attrDescr); while (! lines.isEmpty()) { line = lines.remove(); if(line.toString().equals("-")) { break; } Attribute a = readSingleValueAttribute(lines, line, entryDN, attrDescr); modAttr.getValues().addAll(a.getValues()); } LDAPAttribute ldapAttr = new LDAPAttribute(modAttr); LDAPModification mod = new LDAPModification(modType, ldapAttr); modifications.add(mod); } return new ModifyChangeRecordEntry(entryDN, modifications); } /** * Parse a delete change record entry from LDIF. * * @param entryDN * The name of the entry being deleted. * @param lines * The lines to parse. * @return Returns the parsed delete change record entry. * @throws LDIFException * If there was an error when parsing the change record. */ private ChangeRecordEntry parseDeleteChangeRecordEntry(DN entryDN, LinkedList<StringBuilder> lines) throws LDIFException { assert debugEnter(CLASS_NAME, "parseDeleteChangeRecordEntry", String.valueOf(entryDN), String.valueOf(lines), String.valueOf(lineNumber)); if(!lines.isEmpty()) { int msgID = MSGID_LDIF_INVALID_DELETE_ATTRIBUTES; String message = getMessage(msgID); throw new LDIFException(msgID, message, lineNumber, true); } return new DeleteChangeRecordEntry(entryDN); } /** * Parse an add change record entry from LDIF. * * @param entryDN * The name of the entry being added. * @param lines * The lines to parse. * @return Returns the parsed add change record entry. * @throws LDIFException * If there was an error when parsing the change record. */ private ChangeRecordEntry parseAddChangeRecordEntry(DN entryDN, LinkedList<StringBuilder> lines) throws LDIFException { assert debugEnter(CLASS_NAME, "parseAddChangeRecordEntry", String.valueOf(entryDN), String.valueOf(lines), String.valueOf(lineNumber)); HashMap<ObjectClass,String> objectClasses = new HashMap<ObjectClass,String>(); HashMap<AttributeType,List<Attribute>> attributes = new HashMap<AttributeType, List<Attribute>>(); for(StringBuilder line : lines) { readAttribute(lines, line, entryDN, objectClasses, attributes, attributes); } // Reconstruct the object class attribute. AttributeType ocType = DirectoryServer.getObjectClassAttributeType(); LinkedHashSet<AttributeValue> ocValues = new LinkedHashSet<AttributeValue>(objectClasses.size()); for (String value : objectClasses.values()) { AttributeValue av = new AttributeValue(ocType, value); ocValues.add(av); } Attribute ocAttr = new Attribute(ocType, "objectClass", ocValues); List<Attribute> ocAttrList = new ArrayList<Attribute>(1); ocAttrList.add(ocAttr); attributes.put(ocType, ocAttrList); return new AddChangeRecordEntry(entryDN, attributes); } /** * Parse colon position in an attribute description. * * @param lines * The current set of lines. * @param line * The current line. * @return The colon position. * @throws LDIFException * If the colon was badly placed or not found. */ private int parseColonPosition(LinkedList<StringBuilder> lines, StringBuilder line) throws LDIFException { assert debugEnter(CLASS_NAME, "parseColonPosition", String.valueOf(lines), String.valueOf(lineNumber)); int colonPos = line.indexOf(":"); if (colonPos <= 0) { int msgID = MSGID_LDIF_NO_ATTR_NAME; String message = getMessage(msgID, lastEntryLineNumber, line.toString()); logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true); } return colonPos; } /** * Parse a single attribute value from a line of LDIF. * * @param lines * The current set of lines. * @param line * The current line. * @param entryDN * The DN of the entry being parsed. * @param colonPos * The position of the separator colon in the line. * @param attrName * The name of the attribute being parsed. * @return The parsed attribute value. * @throws LDIFException * If an error occurred when parsing the attribute value. */ private ASN1OctetString parseSingleValue( LinkedList<StringBuilder> lines, StringBuilder line, DN entryDN, int colonPos, String attrName) throws LDIFException { assert debugEnter(CLASS_NAME, "parseSingleValue", String.valueOf(lines), String.valueOf(line), String.valueOf(entryDN), String.valueOf(colonPos), String.valueOf(attrName)); // Look at the character immediately after the colon. If there is // none, then assume an attribute with an empty value. If it is another // colon, then the value must be base64-encoded. If it is a less-than // sign, then assume that it is a URL. Otherwise, it is a regular value. int length = line.length(); ASN1OctetString value; if (colonPos == (length-1)) { value = new ASN1OctetString(); } else { char c = line.charAt(colonPos+1); if (c == ':') { // The value is base64-encoded. Find the first non-blank // character, take the rest of the line, and base64-decode it. int pos = colonPos+2; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } try { value = new ASN1OctetString(Base64.decode(line.substring(pos))); } catch (Exception e) { // The value did not have a valid base64-encoding. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_COULD_NOT_BASE64_DECODE_ATTR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, line, String.valueOf(e)); logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } } else if (c == '<') { // Find the first non-blank character, decode the rest of the // line as a URL, and read its contents. int pos = colonPos+2; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } URL contentURL; try { contentURL = new URL(line.substring(pos)); } catch (Exception e) { // The URL was malformed or had an invalid protocol. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_INVALID_URL; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, String.valueOf(attrName), String.valueOf(e)); logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } InputStream inputStream = null; ByteArrayOutputStream outputStream = null; try { outputStream = new ByteArrayOutputStream(); inputStream = contentURL.openConnection().getInputStream(); int bytesRead; while ((bytesRead = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, bytesRead); } value = new ASN1OctetString(outputStream.toByteArray()); } catch (Exception e) { // We were unable to read the contents of that URL for some // reason. assert debugException(CLASS_NAME, "readAttribute", e); int msgID = MSGID_LDIF_URL_IO_ERROR; String message = getMessage(msgID, String.valueOf(entryDN), lastEntryLineNumber, String.valueOf(attrName), String.valueOf(contentURL), String.valueOf(e)); logToRejectWriter(lines, message); throw new LDIFException(msgID, message, lastEntryLineNumber, true, e); } finally { if (outputStream != null) { try { outputStream.close(); } catch (Exception e) {} } if (inputStream != null) { try { inputStream.close(); } catch (Exception e) {} } } } else { // The rest of the line should be the value. Skip over any // spaces and take the rest of the line as the value. int pos = colonPos+1; while ((pos < length) && (line.charAt(pos) == ' ')) { pos++; } value = new ASN1OctetString(line.substring(pos)); } } return value; } /** * Log a message to the reject writer if one is configured. * * @param lines * The set of rejected lines. * @param message * The associated error message. */ private void logToRejectWriter(LinkedList<StringBuilder> lines, String message) { assert debugEnter(CLASS_NAME, "logToRejectWriter", String.valueOf(lines), String.valueOf(message)); BufferedWriter rejectWriter = importConfig.getRejectWriter(); if (rejectWriter != null) { try { rejectWriter.write("# "); rejectWriter.write(message); rejectWriter.newLine(); for (StringBuilder sb : lines) { rejectWriter.write(sb.toString()); rejectWriter.newLine(); } rejectWriter.newLine(); } catch (Exception e) { assert debugException(CLASS_NAME, "logToRejectWriter", e); } } } } opendj-sdk/opends/src/server/org/opends/server/util/ModifyChangeRecordEntry.java
@@ -28,20 +28,16 @@ import static org.opends.server.loggers.Debug.debugConstructor; import static org.opends.server.loggers.Debug.debugEnter; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.messages.UtilityMessages.*; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.opends.server.protocols.ldap.LDAPAttribute; import org.opends.server.protocols.ldap.LDAPModification; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeValue; import org.opends.server.types.DN; import org.opends.server.types.ModificationType; @@ -59,38 +55,47 @@ "org.opends.server.util.ModifyChangeRecordEntry"; private LDIFReader reader; /** * The modifications for this change record. */ private final List<LDAPModification> modifications; private ArrayList<LDAPModification> modifications = new ArrayList<LDAPModification>(); /** * Creates a new entry with the provided information. * * @param dn The distinguished name for this entry. * @param reader The LDIFReader instance used to read the entries. * @param modifications The modifications for this change record. */ public ModifyChangeRecordEntry(DN dn, LDIFReader reader) public ModifyChangeRecordEntry(DN dn, Collection<LDAPModification> modifications) { super(dn, reader); super(dn); this.reader = reader; assert debugConstructor(CLASS_NAME, String.valueOf(dn), String.valueOf(modifications)); this.modifications = new ArrayList<LDAPModification>(modifications); } /** * Get the list of modifications from the attributes. * Get the list of modifications. * <p> * The returned list is read-only. * * @return the list of modifications. * @return Returns the unmodifiable list of modifications. */ public ArrayList<LDAPModification> getModifications() public List<LDAPModification> getModifications() { assert debugEnter(CLASS_NAME, "getModifications"); return modifications; return Collections.unmodifiableList(modifications); } /** * Retrieves the name of the change operation type. * @@ -102,84 +107,5 @@ return ChangeOperationType.MODIFY; } /** * Parse the lines and populate the internal structures. * * @param lines The lines to parse. * @param lineNumber The current line number. * * @exception LDIFException if there is an error during parsing. */ public void parse(LinkedList<StringBuilder> lines, long lineNumber) throws LDIFException { assert debugEnter(CLASS_NAME, "parse", String.valueOf(lines), String.valueOf(lineNumber)); while(!lines.isEmpty()) { ModificationType modType = null; StringBuilder line = lines.remove(); Attribute attr = reader.readSingleValueAttribute(lines, line, getDN(), null); String name = attr.getName(); LinkedHashSet<AttributeValue> values = attr.getValues(); // Only 1 entry should be present if(values.size() != 1) { int msgID = MSGID_LDIF_INVALID_MODIFY_ATTRIBUTE_VAL; String message = getMessage(msgID, name); throw new LDIFException(msgID, message, lineNumber, true); } // Get the attribute description String attrDescr = values.iterator().next().getStringValue(); String lowerName = name.toLowerCase(); if(lowerName.equals("add")) { modType = ModificationType.ADD; } else if(lowerName.equals("delete")) { modType = ModificationType.DELETE; } else if(lowerName.equals("replace")) { modType = ModificationType.REPLACE; } else if(lowerName.equals("increment")) { modType = ModificationType.INCREMENT; } else { // Invalid attribute name. int msgID = MSGID_LDIF_INVALID_MODIFY_ATTRIBUTE; String message = getMessage(msgID, name, "add, delete, replace, increment"); throw new LDIFException(msgID, message, lineNumber, true); } // Now go through the rest of the attributes till the "-" line is reached. Attribute modAttr = LDIFReader.parseAttrDescription(attrDescr); while (! lines.isEmpty()) { line = lines.remove(); if(line.toString().equals("-")) { break; } Attribute a = reader.readSingleValueAttribute(lines, line, getDN(), attrDescr); modAttr.getValues().addAll(a.getValues()); } LDAPAttribute ldapAttr = new LDAPAttribute(modAttr); LDAPModification mod = new LDAPModification(modType, ldapAttr); modifications.add(mod); } } } opendj-sdk/opends/src/server/org/opends/server/util/ModifyDNChangeRecordEntry.java
@@ -30,16 +30,7 @@ import static org.opends.server.loggers.Debug.debugConstructor; import static org.opends.server.loggers.Debug.debugEnter; import static org.opends.server.loggers.Debug.debugException; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.messages.UtilityMessages.*; import java.util.LinkedHashSet; import java.util.LinkedList; import org.opends.server.core.DirectoryException; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeValue; import org.opends.server.types.DN; import org.opends.server.types.RDN; @@ -58,32 +49,40 @@ private static final String CLASS_NAME = "org.opends.server.util.ModifyDNChangeRecordEntry"; private LDIFReader reader; // The new RDN. private RDN newRDN = null; private final RDN newRDN; // The new superior DN. private DN newSuperiorDN = null; private final DN newSuperiorDN; // Delete the old RDN? private boolean deleteOldRDN = false; private final boolean deleteOldRDN; /** * Creates a new entry with the provided information. * * @param dn The distinguished name for this entry. * @param reader The LDIFReader instance used to read the entries. * @param dn * The distinguished name for this entry. * @param newSuperiorDN * The new superior DN. * @param newRDN * The new RDN. * @param deleteOldRDN * Delete the old RDN? */ public ModifyDNChangeRecordEntry(DN dn, LDIFReader reader) public ModifyDNChangeRecordEntry(DN dn, DN newSuperiorDN, RDN newRDN, boolean deleteOldRDN) { super(dn, reader); super(dn); assert debugConstructor(CLASS_NAME, String.valueOf(dn), String.valueOf(reader)); String.valueOf(newSuperiorDN), String.valueOf(newRDN), String.valueOf(deleteOldRDN)); this.reader = reader; this.newSuperiorDN = newSuperiorDN; this.newRDN = newRDN; this.deleteOldRDN = deleteOldRDN; } @@ -137,147 +136,5 @@ return ChangeOperationType.MODIFY_DN; } /** * Parse the lines and populate the internal structures. * * @param lines The lines to parse. * @param lineNumber The current line number. * * @exception LDIFException if there is an error during parsing. */ public void parse(LinkedList<StringBuilder> lines, long lineNumber) throws LDIFException { assert debugEnter(CLASS_NAME, "parse", String.valueOf(lines), String.valueOf(lineNumber)); if(lines.isEmpty()) { int msgID = MSGID_LDIF_NO_MOD_DN_ATTRIBUTES; String message = getMessage(msgID); throw new LDIFException(msgID, message, lineNumber, true); } StringBuilder line = lines.remove(); String rdnStr = getAttributeValue(lines, line, "newrdn"); try { newRDN = RDN.decode(rdnStr); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "parse", de); int msgID = MSGID_LDIF_INVALID_DN; String message = getMessage(msgID, lineNumber, line.toString(), de.getErrorMessage()); throw new LDIFException(msgID, message, lineNumber, true); } catch (Exception e) { assert debugException(CLASS_NAME, "parse", e); int msgID = MSGID_LDIF_INVALID_DN; String message = getMessage(msgID, lineNumber, line.toString(), e.getMessage()); throw new LDIFException(msgID, message, lineNumber, true); } if(lines.isEmpty()) { int msgID = MSGID_LDIF_NO_DELETE_OLDRDN_ATTRIBUTE; String message = getMessage(msgID); throw new LDIFException(msgID, message, lineNumber, true); } lineNumber++; line = lines.remove(); String delStr = getAttributeValue(lines, line, "deleteoldrdn"); if(delStr.equalsIgnoreCase("false") || delStr.equalsIgnoreCase("no") || delStr.equalsIgnoreCase("0")) { deleteOldRDN = false; } else if(delStr.equalsIgnoreCase("true") || delStr.equalsIgnoreCase("yes") || delStr.equalsIgnoreCase("1")) { deleteOldRDN = true; } else { int msgID = MSGID_LDIF_INVALID_DELETE_OLDRDN_ATTRIBUTE; String message = getMessage(msgID, delStr); throw new LDIFException(msgID, message, lineNumber, true); } if(!lines.isEmpty()) { lineNumber++; line = lines.remove(); String dnStr = getAttributeValue(lines, line, "newsuperior"); try { newSuperiorDN = DN.decode(dnStr); } catch (DirectoryException de) { assert debugException(CLASS_NAME, "parse", de); int msgID = MSGID_LDIF_INVALID_DN; String message = getMessage(msgID, lineNumber, line.toString(), de.getErrorMessage()); throw new LDIFException(msgID, message, lineNumber, true); } catch (Exception e) { assert debugException(CLASS_NAME, "parse", e); int msgID = MSGID_LDIF_INVALID_DN; String message = getMessage(msgID, lineNumber, line.toString(), e.getMessage()); throw new LDIFException(msgID, message, lineNumber, true); } } } /** * Return the string value for the specified attribute name which * only has one value. * * @param lines The set of lines for this change record entry. * @param line The line currently being examined. * @param attributeName The attribute name * * @return the string value for the attribute name. * * @throws LDIFException If a problem occurs while attempting to determine * the attribute value. */ private String getAttributeValue(LinkedList<StringBuilder> lines, StringBuilder line, String attributeName) throws LDIFException { assert debugEnter(CLASS_NAME, "getAttributeValue", String.valueOf(lines), String.valueOf(line), String.valueOf(attributeName)); Attribute attr = reader.readSingleValueAttribute(lines, line, getDN(), attributeName); LinkedHashSet<AttributeValue> values = attr.getValues(); // Only 1 entry should be present if(values.size() != 1) { int msgID = MSGID_LDIF_INVALID_MODIFY_ATTRIBUTE_VAL; String message = getMessage(msgID, attributeName); throw new LDIFException(msgID, message); } // Get the attribute value Object[] vals = values.toArray(); return (((AttributeValue)vals[0]).getStringValue()); } } opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/TestAddChangeRecordEntry.java
@@ -26,12 +26,16 @@ */ package org.opends.server.util; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.opends.server.TestCaseUtils; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.DN; import org.opends.server.types.LDIFImportConfig; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -45,8 +49,11 @@ * been overridden. */ public final class TestAddChangeRecordEntry extends UtilTestCase { // An empty LDIF reader. private LDIFReader emptyReader; // Set of attributes. private Map<AttributeType, List<Attribute>> attributes; // The attribute being added. private Attribute attribute; /** * Once-only initialization. @@ -60,9 +67,11 @@ // start the server. TestCaseUtils.startServer(); InputStream stream = new ByteArrayInputStream(new byte[0]); LDIFImportConfig config = new LDIFImportConfig(stream); emptyReader = new LDIFReader(config); attributes = new HashMap<AttributeType, List<Attribute>>(); attribute = new Attribute("cn", "hello world"); ArrayList<Attribute> alist = new ArrayList<Attribute>(1); alist.add(attribute); attributes.put(attribute.getAttributeType(), alist); } /** @@ -73,7 +82,7 @@ */ @Test public void testConstructorNullDN() throws Exception { AddChangeRecordEntry entry = new AddChangeRecordEntry(null, emptyReader); AddChangeRecordEntry entry = new AddChangeRecordEntry(null, attributes); Assert.assertEquals(entry.getDN(), new DN()); } @@ -87,7 +96,7 @@ @Test public void testConstructorEmptyDN() throws Exception { AddChangeRecordEntry entry = new AddChangeRecordEntry(new DN(), emptyReader); attributes); Assert.assertEquals(entry.getDN(), new DN()); } @@ -104,7 +113,7 @@ DN testDN2 = DN.decode("dc=hello, dc=world"); AddChangeRecordEntry entry = new AddChangeRecordEntry(testDN1, emptyReader); attributes); Assert.assertEquals(entry.getDN(), testDN2); } @@ -117,28 +126,41 @@ */ @Test public void testChangeOperationType() throws Exception { AddChangeRecordEntry entry = new AddChangeRecordEntry(null, emptyReader); AddChangeRecordEntry entry = new AddChangeRecordEntry(null, attributes); Assert.assertEquals(entry.getChangeOperationType(), ChangeOperationType.ADD); } /** * Tests parse and getAttributes methods. * <p> * Due to tight coupling between the * {@link AddChangeRecordEntry#parse(java.util.LinkedList, long)} * method and the {@link LDIFReader} class it is not easy to test the * {@link AddChangeRecordEntry#getAttributes()} method. Instead, we'll * test that in the {@link LDIFReader} test suite. * Tests getAttributes method for empty modifications. * * @throws Exception * If the test failed unexpectedly. */ @Test(enabled = false) public void testGetAttributes() throws Exception { // FIXME: fix tight-coupling between parse() and LDIFReader. Assert.assertTrue(false); @Test public void testGetAttributesEmpty() throws Exception { Map<AttributeType, List<Attribute>> empty = Collections.emptyMap(); AddChangeRecordEntry entry = new AddChangeRecordEntry(null, empty); List<Attribute> attrs = entry.getAttributes(); Assert.assertEquals(attrs.size(), 0); } /** * Tests getAttributes method for non-empty modifications. * * @throws Exception * If the test failed unexpectedly. */ @Test public void testGetAttributesNonEmpty() throws Exception { AddChangeRecordEntry entry = new AddChangeRecordEntry(null, attributes); List<Attribute> attrs = entry.getAttributes(); Assert.assertEquals(attrs.size(), 1); Attribute first = attrs.get(0); Assert.assertEquals(first, attribute); } } opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/TestChangeRecordEntry.java
@@ -26,8 +26,6 @@ */ package org.opends.server.util; import java.util.LinkedList; import org.opends.server.TestCaseUtils; import org.opends.server.types.DN; import org.testng.Assert; @@ -65,15 +63,6 @@ // Will not use. return null; } /** * {@inheritDoc} */ @Override public void parse(LinkedList<StringBuilder> lines, long lineNumber) throws LDIFException { // Will not use. } } /** @@ -88,7 +77,7 @@ // start the server. TestCaseUtils.startServer(); } /** * Tests the constructor with null DN. * @@ -130,23 +119,4 @@ Assert.assertEquals(entry.getDN(), testDN2); } /** * Tests the set DN method. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testConstructorNonNullDN" }) public void testSetDN() throws Exception { DN testDN1 = DN.decode("dc=hello, dc=world"); DN testDN2 = DN.decode("dc=goodbye, dc=world"); DN testDN3 = DN.decode("dc=goodbye, dc=world"); MyChangeRecordEntry entry = new MyChangeRecordEntry(testDN1); entry.setDN(testDN2); Assert.assertEquals(entry.getDN(), testDN3); } } opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/TestDeleteChangeRecordEntry.java
@@ -26,12 +26,8 @@ */ package org.opends.server.util; import java.io.ByteArrayInputStream; import java.io.InputStream; import org.opends.server.TestCaseUtils; import org.opends.server.types.DN; import org.opends.server.types.LDIFImportConfig; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -45,9 +41,6 @@ * been overridden. */ public final class TestDeleteChangeRecordEntry extends UtilTestCase { // An empty LDIF reader. private LDIFReader emptyReader; /** * Once-only initialization. * @@ -59,10 +52,6 @@ // This test suite depends on having the schema available, so we'll // start the server. TestCaseUtils.startServer(); InputStream stream = new ByteArrayInputStream(new byte[0]); LDIFImportConfig config = new LDIFImportConfig(stream); emptyReader = new LDIFReader(config); } /** @@ -73,8 +62,7 @@ */ @Test public void testConstructorNullDN() throws Exception { DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(null, emptyReader); DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(null); Assert.assertEquals(entry.getDN(), new DN()); } @@ -87,8 +75,7 @@ */ @Test public void testConstructorEmptyDN() throws Exception { DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(new DN(), emptyReader); DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(new DN()); Assert.assertEquals(entry.getDN(), new DN()); } @@ -104,8 +91,7 @@ DN testDN1 = DN.decode("dc=hello, dc=world"); DN testDN2 = DN.decode("dc=hello, dc=world"); DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(testDN1, emptyReader); DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(testDN1); Assert.assertEquals(entry.getDN(), testDN2); } @@ -118,28 +104,10 @@ */ @Test public void testChangeOperationType() throws Exception { DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(null, emptyReader); DeleteChangeRecordEntry entry = new DeleteChangeRecordEntry(null); Assert.assertEquals(entry.getChangeOperationType(), ChangeOperationType.DELETE); } /** * Tests parse method. * <p> * Due to tight coupling between the * {@link DeleteChangeRecordEntry#parse(java.util.LinkedList, long)} * method and the {@link LDIFReader} class we'll test this method in * the {@link LDIFReader} test suite. * * @throws Exception * If the test failed unexpectedly. */ @Test(enabled = false) public void testParse() throws Exception { // FIXME: fix tight-coupling between parse() and LDIFReader. Assert.assertTrue(false); } } opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/TestLDIFReader.java
New file @@ -0,0 +1,980 @@ /* * 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/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * 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/opends/resource/legal-notices/OpenDS.LICENSE. 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 * * * Portions Copyright 2006 Sun Microsystems, Inc. */ package org.opends.server.util; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import org.opends.server.TestCaseUtils; import org.opends.server.core.DirectoryServer; import org.opends.server.protocols.ldap.LDAPModification; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.Modification; import org.opends.server.types.ModificationType; import org.opends.server.types.ObjectClass; import org.opends.server.types.RDN; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * This class defines a set of tests for the * {@link org.opends.server.util.LDIFReader} class. */ public final class TestLDIFReader extends UtilTestCase { // Top object class. private ObjectClass OC_TOP; // Person object class. private ObjectClass OC_PERSON; // Object class attribute type. private AttributeType AT_OC; // Common name attribute type. private AttributeType AT_CN; // Surname attribute type. private AttributeType AT_SN; // Description attribute type. private AttributeType AT_DESCR; // Telephone number attribute type. private AttributeType AT_TELN; // Temporary file containing an attribute value. private File TEMP_FILE = null; // Temporary file content. private static final String TEMP_FILE_STRING = "hello world"; // Temporary file LDIF. private static final String TEMP_FILE_LDIF = "dn: cn=john smith, dc=com\n" + "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "description:< file:///"; /** * String of valid LDIF change records. * * Take from example 6 in the LDIF RFC + a couple of additions. */ private static final String VALID_LDIF = "version: 1\n" + "# Add a new entry\n" + "dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com\n" + "changetype: add\n" + "objectclass: top\n" + "objectclass: person\n" + "objectclass: organizationalPerson\n" + "cn: Fiona Jensen\n" + "sn: Jensen\n" + "uid: fiona\n" + "telephonenumber: +1 408 555 1212\n" + "\n" + "# Delete an existing entry\n" + "dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com\n" + "changetype: delete\n" + "\n" + "# Modify an entry's relative distinguished name\n" + "dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com\n" + "changetype: modrdn\n" + "newrdn: cn=Paula Jensen\n" + "deleteoldrdn: 1\n" + "\n" + "# Rename an entry and move all of its children to a new location in\n" + "# the directory tree (only implemented by LDAPv3 servers).\n" + "dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com\n" + "changetype: modrdn\n" + "newrdn: ou=Product Development Accountants\n" + "deleteoldrdn: 0\n" + "newsuperior: ou=Accounting, dc=airius, dc=com\n" + "\n" + "# Modify an entry: add an additional value to the postaladdress\n" + "# attribute, completely delete the description attribute, replace\n" + "# the telephonenumber attribute with two values, and delete a specific\n" + "# value from the facsimiletelephonenumber attribute\n" + "dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com\n" + "changetype: modify\n" + "add: postaladdress\n" + "postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086\n" + "-\n" + "delete: description\n" + "-\n" + "replace: telephonenumber\n" + "telephonenumber: +1 408 555 1234\n" + "telephonenumber: +1 408 555 5678\n" + "-\n" + "delete: facsimiletelephonenumber\n" + "facsimiletelephonenumber: +1 408 555 9876\n" + "-\n" + "\n" + "# Modify an entry: replace the postaladdress attribute with an empty\n" + "# set of values (which will cause the attribute to be removed), and\n" + "# delete the entire description attribute. Note that the first will\n" + "# always succeed, while the second will only succeed if at least\n" + "# one value for the description attribute is present.\n" + "dn: cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com\n" + "changetype: modify\n" + "replace: postaladdress\n" + "-\n" + "delete: description\n" + "-\n" + "\n" + "# Modify rootDSE.\n" + "dn: \n" + "changetype: modify\n" + "delete: description\n" + "-\n" + "\n" + "# Modify base64 DN.\n" + "dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz\n" + "# dn:: uid=<uid>,ou=<JapaneseOU>,o=Airius\n" + "changetype:: bW9kaWZ5\n" + "delete: description\n" + "-\n" + "\n"; /** * Once-only initialization. * * @throws Exception * If an unexpected error occurred. */ @BeforeClass public void setUp() throws Exception { // This test suite depends on having the schema available, so we'll // start the server. TestCaseUtils.startServer(); // Initialize schema bits. OC_TOP = DirectoryServer.getObjectClass("top"); OC_PERSON = DirectoryServer.getObjectClass("person"); AT_OC = DirectoryServer.getObjectClassAttributeType(); AT_CN = DirectoryServer.getAttributeType("cn"); AT_SN = DirectoryServer.getAttributeType("sn"); AT_DESCR = DirectoryServer.getAttributeType("description"); AT_TELN = DirectoryServer.getAttributeType("telephonenumber"); // Create a temporary file containing an attribute value. TEMP_FILE = File.createTempFile("tmp", "txt"); OutputStream out = null; try { out = new FileOutputStream(TEMP_FILE); out.write(TEMP_FILE_STRING.getBytes("UTF-8")); } finally { if (out != null) { out.close(); } } } /** * Once-only tear-down. * * @throws Exception * If an unexpected error occurred. */ @AfterClass public void tearDown() throws Exception { if (TEMP_FILE != null) { TEMP_FILE.delete(); } } /** * Check the initial state of an LDIF reader. * * @throws Exception * If the test failed unexpectedly. */ @Test public void testInitialState() throws Exception { LDIFReader reader = createLDIFReader(""); try { Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 0); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), -1); } finally { reader.close(); } } /** * Attempt to read an entry from an empty LDIF stream. * * @throws Exception * If the test failed unexpectedly. */ @Test public void testReadEntryEmptyStream() throws Exception { LDIFReader reader = createLDIFReader(""); try { Entry entry = reader.readEntry(); Assert.assertNull(entry); Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 0); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), -1); } finally { reader.close(); } } /** * Attempt to read an entry from an empty LDIF stream containing just * the LDIF version. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testReadEntryEmptyStream" }) public void testReadEntryEmptyStreamVersion() throws Exception { LDIFReader reader = createLDIFReader("version: 1\n"); try { Entry entry = reader.readEntry(); Assert.assertNull(entry); Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 0); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), 1); } finally { reader.close(); } } /** * Attempt to read a change record from an empty LDIF stream. * * @throws Exception * If the test failed unexpectedly. */ @Test public void testChangeRecordEmptyStream() throws Exception { LDIFReader reader = createLDIFReader(""); try { ChangeRecordEntry change = reader.readChangeRecord(true); Assert.assertNull(change); Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 0); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), -1); } finally { reader.close(); } } /** * Attempt to read a single entry. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testReadEntryEmptyStream" }) public void testReadEntrySingle() throws Exception { final String ldifString = "dn: cn=john, dc=foo, dc=com\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n"; LDIFReader reader = createLDIFReader(ldifString); try { Entry entry = reader.readEntry(); Assert.assertNotNull(entry); Assert.assertEquals(entry.getDN(), DN .decode("cn=john, dc=foo, dc=com")); Assert.assertTrue(entry.hasObjectClass(OC_TOP)); Assert.assertTrue(entry.hasObjectClass(OC_PERSON)); Assert.assertTrue(entry.hasValue(AT_CN, null, new AttributeValue( AT_CN, "john"))); Assert.assertTrue(entry.hasValue(AT_SN, null, new AttributeValue( AT_SN, "smith"))); Assert.assertNull(reader.readEntry()); Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 1); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), 1); } finally { reader.close(); } } /** * Attempt to read an entry containing a folded line. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testReadEntrySingle" }) public void testReadEntryFoldedLine() throws Exception { final String ldifString = "dn: cn=john, dc=foo, dc=com\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "description: once upon a time\n" + " in the west\n"; LDIFReader reader = createLDIFReader(ldifString); try { Entry entry = reader.readEntry(); Assert.assertNotNull(entry); Assert.assertTrue(entry.hasValue(AT_DESCR, null, new AttributeValue( AT_DESCR, "once upon a time in the west"))); } finally { reader.close(); } } /** * Attempt to read an entry containing a base64 line. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testReadEntrySingle" }) public void testReadEntryBase64() throws Exception { final String ldifString = "dn: cn=john, dc=foo, dc=com\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "description:: b25jZSB1cG9uIGEgdGltZSBpbiB0aGUgd2VzdA==\n"; LDIFReader reader = createLDIFReader(ldifString); try { Entry entry = reader.readEntry(); Assert.assertNotNull(entry); Assert.assertTrue(entry.hasValue(AT_DESCR, null, new AttributeValue( AT_DESCR, "once upon a time in the west"))); } finally { reader.close(); } } /** * Attempt to read multiple entries. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testReadEntrySingle" }) public void testReadEntryMultiple() throws Exception { final String ldifString = "dn: cn=john, dc=foo, dc=com\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "\n" + "dn: cn=anne, dc=foo, dc=com\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: anne\n" + "sn: other\n" + "\n"; LDIFReader reader = createLDIFReader(ldifString); try { reader.readEntry(); Entry entry = reader.readEntry(); Assert.assertNotNull(entry); Assert.assertEquals(entry.getDN(), DN .decode("cn=anne, dc=foo, dc=com")); Assert.assertTrue(entry.hasObjectClass(OC_TOP)); Assert.assertTrue(entry.hasObjectClass(OC_PERSON)); Assert.assertTrue(entry.hasValue(AT_CN, null, new AttributeValue( AT_CN, "anne"))); Assert.assertTrue(entry.hasValue(AT_SN, null, new AttributeValue( AT_SN, "other"))); Assert.assertNull(reader.readEntry()); Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 2); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), 7); } finally { reader.close(); } } /** * Attempt to read multiple changes. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testChangeRecordEmptyStream" }) public void testReadChangeMultiple() throws Exception { LDIFReader reader = createLDIFReader(VALID_LDIF); try { ChangeRecordEntry change; AddChangeRecordEntry add; DeleteChangeRecordEntry delete; ModifyChangeRecordEntry modify; ModifyDNChangeRecordEntry modifyDN; DN dn; RDN rdn; Iterator<LDAPModification> i; Modification mod; Attribute attr; LinkedHashSet<AttributeValue> values; // Change record #1. change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof AddChangeRecordEntry); add = (AddChangeRecordEntry) change; dn = DN.decode("cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com"); Assert.assertEquals(add.getDN(), dn); List<Attribute> attrs = new ArrayList<Attribute>(); values = new LinkedHashSet<AttributeValue>(); values.add(new AttributeValue(AT_OC, "top")); values.add(new AttributeValue(AT_OC, "person")); values.add(new AttributeValue(AT_OC, "organizationalPerson")); attrs.add(new Attribute(AT_OC, "objectclass", values)); attrs.add(new Attribute("cn", "Fiona Jensen")); attrs.add(new Attribute("sn", "Jensen")); attrs.add(new Attribute("uid", "fiona")); attrs.add(new Attribute("telephonenumber", "+1 408 555 1212")); Assert.assertTrue(add.getAttributes().containsAll(attrs)); // Change record #2. change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof DeleteChangeRecordEntry); delete = (DeleteChangeRecordEntry) change; dn = DN.decode("cn=Robert Jensen, ou=Marketing, dc=airius, dc=com"); Assert.assertEquals(delete.getDN(), dn); // Change record #3. change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof ModifyDNChangeRecordEntry); modifyDN = (ModifyDNChangeRecordEntry) change; dn = DN .decode("cn=Paul Jensen, ou=Product Development, dc=airius, dc=com"); Assert.assertEquals(modifyDN.getDN(), dn); rdn = RDN.decode("cn=paula jensen"); Assert.assertEquals(modifyDN.getNewRDN(), rdn); Assert.assertNull(modifyDN.getNewSuperiorDN()); Assert.assertTrue(modifyDN.deleteOldRDN()); // Change record #4. change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof ModifyDNChangeRecordEntry); modifyDN = (ModifyDNChangeRecordEntry) change; dn = DN .decode("ou=PD Accountants, ou=Product Development, dc=airius, dc=com"); Assert.assertEquals(modifyDN.getDN(), dn); rdn = RDN.decode("ou=Product Development Accountants"); Assert.assertEquals(modifyDN.getNewRDN(), rdn); dn = DN.decode("ou=Accounting, dc=airius, dc=com"); Assert.assertEquals(modifyDN.getNewSuperiorDN(), dn); Assert.assertFalse(modifyDN.deleteOldRDN()); // Change record #5. change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof ModifyChangeRecordEntry); modify = (ModifyChangeRecordEntry) change; dn = DN .decode("cn=Paula Jensen, ou=Product Development, dc=airius, dc=com"); Assert.assertEquals(modify.getDN(), dn); i = modify.getModifications().iterator(); Assert.assertTrue(i.hasNext()); mod = i.next().toModification(); Assert.assertEquals(mod.getModificationType(), ModificationType.ADD); attr = new Attribute("postaladdress", "123 Anystreet $ Sunnyvale, CA $ 94086"); Assert.assertEquals(mod.getAttribute(), attr); Assert.assertTrue(i.hasNext()); mod = i.next().toModification(); Assert.assertEquals(mod.getModificationType(), ModificationType.DELETE); attr = new Attribute(AT_DESCR); Assert.assertEquals(mod.getAttribute(), attr); Assert.assertTrue(i.hasNext()); mod = i.next().toModification(); Assert.assertEquals(mod.getModificationType(), ModificationType.REPLACE); values = new LinkedHashSet<AttributeValue>(); values.add(new AttributeValue(AT_TELN, "+1 408 555 1234")); values.add(new AttributeValue(AT_TELN, "+1 408 555 5678")); attr = new Attribute(AT_TELN, "telephonenumber", values); Assert.assertEquals(mod.getAttribute(), attr); Assert.assertTrue(i.hasNext()); mod = i.next().toModification(); Assert.assertEquals(mod.getModificationType(), ModificationType.DELETE); attr = new Attribute("facsimiletelephonenumber", "+1 408 555 9876"); Assert.assertEquals(mod.getAttribute(), attr); Assert.assertFalse(i.hasNext()); // Change record #6. change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof ModifyChangeRecordEntry); modify = (ModifyChangeRecordEntry) change; dn = DN .decode("cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com"); Assert.assertEquals(modify.getDN(), dn); i = modify.getModifications().iterator(); Assert.assertTrue(i.hasNext()); mod = i.next().toModification(); Assert.assertEquals(mod.getModificationType(), ModificationType.REPLACE); attr = new Attribute(DirectoryServer .getAttributeType("postaladdress")); Assert.assertEquals(mod.getAttribute(), attr); // Change record #7. change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof ModifyChangeRecordEntry); modify = (ModifyChangeRecordEntry) change; Assert.assertTrue(modify.getDN().isNullDN()); i = modify.getModifications().iterator(); Assert.assertTrue(i.hasNext()); mod = i.next().toModification(); Assert.assertEquals(mod.getModificationType(), ModificationType.DELETE); attr = new Attribute(AT_DESCR); Assert.assertEquals(mod.getAttribute(), attr); // Change record #8. change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof ModifyChangeRecordEntry); modify = (ModifyChangeRecordEntry) change; dn = DN.decode("uid=rogasawara, ou=\u55b6\u696d\u90e8, o=airius"); Assert.assertEquals(modify.getDN(), dn); i = modify.getModifications().iterator(); Assert.assertTrue(i.hasNext()); mod = i.next().toModification(); Assert.assertEquals(mod.getModificationType(), ModificationType.DELETE); attr = new Attribute(AT_DESCR); Assert.assertEquals(mod.getAttribute(), attr); Assert.assertFalse(i.hasNext()); // Check final state. Assert.assertNull(reader.readChangeRecord(false)); Assert.assertEquals(reader.getEntriesIgnored(), 0); Assert.assertEquals(reader.getEntriesRead(), 0); Assert.assertEquals(reader.getEntriesRejected(), 0); Assert.assertEquals(reader.getLastEntryLineNumber(), 72); } finally { reader.close(); } } /** * Attempt to read multiple changes and rejects one. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testReadChangeMultiple" }) public void testReadChangeMultipleAndReject() throws Exception { LDIFReader reader = createLDIFReader(VALID_LDIF); try { reader.readChangeRecord(false); reader.readChangeRecord(false); reader.readChangeRecord(false); reader.readChangeRecord(false); reader.rejectLastEntry("Rejected"); reader.readChangeRecord(false); reader.rejectLastEntry("Rejected"); reader.readChangeRecord(false); reader.readChangeRecord(false); reader.readChangeRecord(false); // Check final state. Assert.assertNull(reader.readChangeRecord(false)); Assert.assertEquals(reader.getEntriesRejected(), 2); } finally { reader.close(); } } /** * Attempt to read a change containing a file-based attribute. * * @throws Exception * If the test failed unexpectedly. */ @Test(dependsOnMethods = { "testReadChangeMultiple" }) public void testReadChangeWithFileBaseAttribute() throws Exception { StringBuilder buffer = new StringBuilder(TEMP_FILE_LDIF); buffer.append(TEMP_FILE.getCanonicalPath()); buffer.append("\n"); LDIFReader reader = createLDIFReader(buffer.toString()); try { ChangeRecordEntry change = reader.readChangeRecord(false); Assert.assertTrue(change instanceof AddChangeRecordEntry); AddChangeRecordEntry add = (AddChangeRecordEntry) change; DN dn = DN.decode("cn=john smith, dc=com"); Assert.assertEquals(add.getDN(), dn); Attribute attr = new Attribute("description", TEMP_FILE_STRING); Assert.assertTrue(add.getAttributes().contains(attr)); // Check final state. Assert.assertNull(reader.readChangeRecord(false)); } finally { reader.close(); } } /** * LDIF change reader - invalid data provider. * * @return Returns an array of invalid LDIF change records. */ @DataProvider(name = "invalidLDIFChangeRecords") public Object[][] createInvalidLDIFChangeRecords() { return new Object[][] { { "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "dn: cn=john smith, dc=com\n" + "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { ": cn=john smith, dc=com\n" + "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "x: cn=john smith, dc=com\n" + "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: foo\n" + "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn,=john smith, dc=com\n" + "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "chaxxngetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: foo\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "changetype:: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + ": add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "changetype:\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: add\n" + "xxxx\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: add\n" + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "cn: john\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: add\n" + ": top\n" + "objectClass: person\n" + "cn: john\n" + "objectClass: person\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: add\n" + "objectclass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "description:: YnJva2VuIGJhc2U2NA*==" }, { "dn:: YnJva2VuIGJhc2U2NA*==" + "changetype: add\n" + "objectclass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn:: Y249YnJva2VuIGJhc2U2NCBkbix4" + "changetype: add\n" + "objectclass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: add\n" + "objectclass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "description:< brok@n:///bad/url" }, { "dn: cn=john smith, dc=com\n" + "changetype: add\n" + "objectclass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "description:< file:///bad/path/name" }, { "dn: cn=john smith, dc=com\n" + "changetype: delete\n" + "objectclass: top\n" + "objectClass: person\n" + "cn: john\n" + "sn: smith\n" + "description:< file:///bad/path/name" }, { "dn: cn=john smith, dc=com\n" + "changetype: modrdn\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: modrdn\n" + "newrdn: x\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: modrdn\n" + "newrdn: cn=foo\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: modrdn\n" + "newrdn: cn=foo\n" + "deleteoldxx: xxx\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: modrdn\n" + "newrdn: cn=foo\n" + "deleteoldrdn: xxx\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: modrdn\n" + "newrdn: cn=foo\n" + "deleteoldrdn: 0\n" + "newsu: xxxx\n" }, { "dn: cn=john smith, dc=com\n" + "changetype: modrdn\n" + "newrdn: cn=foo\n" + "deleteoldrdn: 0\n" + "newsuperior: xxxx\n" }, }; } /** * Tests the read change record method against invalid LDIF records. * * @param ldifString * The invalid LDIF change record. * @throws Exception * If the test failed unexpectedly. */ @Test(dataProvider = "invalidLDIFChangeRecords", expectedExceptions = { LDIFException.class }) public void testReadChangeInvalidData(String ldifString) throws Exception { LDIFReader reader = createLDIFReader(ldifString); ChangeRecordEntry change = null; try { change = reader.readChangeRecord(false); } finally { reader.close(); } Assert.fail("Expected exception but got result: " + change.getChangeOperationType() + " - " + change.getDN()); } /** * Create an LDIF reader from a string of LDIF. * * @param ldifString * The string of LDIF. * * @return Returns the LDIF reader. * @throws Exception * If an error occurred. */ private LDIFReader createLDIFReader(String ldifString) throws Exception { byte[] bytes = StaticUtils.getBytes(ldifString); LDIFReader reader = new LDIFReader(new LDIFImportConfig( new ByteArrayInputStream(bytes))); return reader; } } opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/TestModifyChangeRecordEntry.java
@@ -26,12 +26,16 @@ */ package org.opends.server.util; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.opends.server.TestCaseUtils; import org.opends.server.protocols.ldap.LDAPAttribute; import org.opends.server.protocols.ldap.LDAPModification; import org.opends.server.types.Attribute; import org.opends.server.types.DN; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.ModificationType; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -45,8 +49,11 @@ * been overridden. */ public final class TestModifyChangeRecordEntry extends UtilTestCase { // An empty LDIF reader. private LDIFReader emptyReader; // Set of changes. private List<LDAPModification> modifications; // The attribute being added in the modifications. private Attribute attribute; /** * Once-only initialization. @@ -60,9 +67,13 @@ // start the server. TestCaseUtils.startServer(); InputStream stream = new ByteArrayInputStream(new byte[0]); LDIFImportConfig config = new LDIFImportConfig(stream); emptyReader = new LDIFReader(config); // Create a simple set of modifications. modifications = new ArrayList<LDAPModification>(); attribute = new Attribute("cn", "hello world"); LDAPAttribute lattribute = new LDAPAttribute(attribute); LDAPModification modification = new LDAPModification( ModificationType.ADD, lattribute); modifications.add(modification); } /** @@ -74,7 +85,7 @@ @Test public void testConstructorNullDN() throws Exception { ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(null, emptyReader); modifications); Assert.assertEquals(entry.getDN(), new DN()); } @@ -88,7 +99,7 @@ @Test public void testConstructorEmptyDN() throws Exception { ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(new DN(), emptyReader); modifications); Assert.assertEquals(entry.getDN(), new DN()); } @@ -105,7 +116,7 @@ DN testDN2 = DN.decode("dc=hello, dc=world"); ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(testDN1, emptyReader); modifications); Assert.assertEquals(entry.getDN(), testDN2); } @@ -119,28 +130,43 @@ @Test public void testChangeOperationType() throws Exception { ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(null, emptyReader); modifications); Assert.assertEquals(entry.getChangeOperationType(), ChangeOperationType.MODIFY); } /** * Tests parse and getAttributes methods. * <p> * Due to tight coupling between the * {@link ModifyChangeRecordEntry#parse(java.util.LinkedList, long)} * method and the {@link LDIFReader} class it is not easy to test the * {@link ModifyChangeRecordEntry#getModifications()} method. Instead, * we'll test that in the {@link LDIFReader} test suite. * Tests getModifications method for empty modifications. * * @throws Exception * If the test failed unexpectedly. */ @Test(enabled = false) public void testGetModifications() throws Exception { // FIXME: fix tight-coupling between parse() and LDIFReader. Assert.assertTrue(false); @Test public void testGetModificationsEmpty() throws Exception { List<LDAPModification> empty = Collections.emptyList(); ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(null, empty); List<LDAPModification> mods = entry.getModifications(); Assert.assertEquals(mods.size(), 0); } /** * Tests getModifications method for non-empty modifications. * * @throws Exception * If the test failed unexpectedly. */ @Test public void testGetModificationsNonEmpty() throws Exception { ModifyChangeRecordEntry entry = new ModifyChangeRecordEntry(null, modifications); List<LDAPModification> mods = entry.getModifications(); Assert.assertEquals(mods.size(), 1); LDAPModification first = mods.get(0); Assert.assertEquals(first.getModificationType(), ModificationType.ADD); Assert.assertEquals(first.getAttribute().toAttribute(), attribute); } } opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/TestModifyDNChangeRecordEntry.java
@@ -26,12 +26,9 @@ */ package org.opends.server.util; import java.io.ByteArrayInputStream; import java.io.InputStream; import org.opends.server.TestCaseUtils; import org.opends.server.types.DN; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.RDN; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -45,8 +42,9 @@ * been overridden. */ public final class TestModifyDNChangeRecordEntry extends UtilTestCase { // An empty LDIF reader. private LDIFReader emptyReader; private DN newSuperiorDN; private RDN newRDN; /** * Once-only initialization. @@ -60,9 +58,8 @@ // start the server. TestCaseUtils.startServer(); InputStream stream = new ByteArrayInputStream(new byte[0]); LDIFImportConfig config = new LDIFImportConfig(stream); emptyReader = new LDIFReader(config); newSuperiorDN = DN.decode("dc=com"); newRDN = RDN.decode("dc=foo"); } /** @@ -74,7 +71,7 @@ @Test public void testConstructorNullDN() throws Exception { ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry(null, emptyReader); newSuperiorDN, newRDN, false); Assert.assertEquals(entry.getDN(), new DN()); } @@ -88,7 +85,7 @@ @Test public void testConstructorEmptyDN() throws Exception { ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry( new DN(), emptyReader); new DN(), newSuperiorDN, newRDN, false); Assert.assertEquals(entry.getDN(), new DN()); } @@ -105,7 +102,7 @@ DN testDN2 = DN.decode("dc=hello, dc=world"); ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry( testDN1, emptyReader); testDN1, newSuperiorDN, newRDN, false); Assert.assertEquals(entry.getDN(), testDN2); } @@ -119,63 +116,66 @@ @Test public void testChangeOperationType() throws Exception { ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry(null, emptyReader); newSuperiorDN, newRDN, false); Assert.assertEquals(entry.getChangeOperationType(), ChangeOperationType.MODIFY_DN); } /** * Tests parse and getNewRDN methods. * <p> * Due to tight coupling between the * {@link ModifyDNChangeRecordEntry#parse(java.util.LinkedList, long)} * method and the {@link LDIFReader} class it is not easy to test the * {@link ModifyDNChangeRecordEntry#getNewRDN()} method. Instead, * we'll test that in the {@link LDIFReader} test suite. * Tests getNewRDN method. * * @throws Exception * If the test failed unexpectedly. */ @Test(enabled = false) @Test public void testGetNewRDN() throws Exception { // FIXME: fix tight-coupling between parse() and LDIFReader. Assert.assertTrue(false); ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry(null, newSuperiorDN, newRDN, false); Assert.assertEquals(entry.getNewRDN(), newRDN.duplicate()); } /** * Tests parse and getNewSuperiorDN methods. * <p> * Due to tight coupling between the * {@link ModifyDNChangeRecordEntry#parse(java.util.LinkedList, long)} * method and the {@link LDIFReader} class it is not easy to test the * {@link ModifyDNChangeRecordEntry#getNewSuperiorDN()} method. * Instead, we'll test that in the {@link LDIFReader} test suite. * Tests getNewSuperiorDN method. * * @throws Exception * If the test failed unexpectedly. */ @Test(enabled = false) @Test public void testGetNewSuperiorDN() throws Exception { // FIXME: fix tight-coupling between parse() and LDIFReader. Assert.assertTrue(false); ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry(null, newSuperiorDN, newRDN, false); Assert .assertEquals(entry.getNewSuperiorDN(), newSuperiorDN.duplicate()); } /** * Tests parse and deleteOldRDN methods. * <p> * Due to tight coupling between the * {@link ModifyDNChangeRecordEntry#parse(java.util.LinkedList, long)} * method and the {@link LDIFReader} class it is not easy to test the * {@link ModifyDNChangeRecordEntry#deleteOldRDN()} method. Instead, * we'll test that in the {@link LDIFReader} test suite. * Tests deleteOldRDN method when false. * * @throws Exception * If the test failed unexpectedly. */ @Test(enabled = false) public void testDeleteOldRDN() throws Exception { // FIXME: fix tight-coupling between parse() and LDIFReader. Assert.assertTrue(false); @Test public void testDeleteOldRDNFalse() throws Exception { ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry(null, newSuperiorDN, newRDN, false); Assert.assertEquals(entry.deleteOldRDN(), false); } /** * Tests deleteOldRDN method. * * @throws Exception * If the test failed unexpectedly. */ @Test public void testDeleteOldRDNTrue() throws Exception { ModifyDNChangeRecordEntry entry = new ModifyDNChangeRecordEntry(null, newSuperiorDN, newRDN, true); Assert.assertEquals(entry.deleteOldRDN(), true); } }