sdk/src/com/sun/opends/sdk/tools/LDAPModify.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2009 Sun Microsystems, Inc. * Copyright 2009-2010 Sun Microsystems, Inc. */ package com.sun.opends.sdk.tools; @@ -762,13 +762,12 @@ reader = new LDIFChangeRecordReader(getInputStream()); } ChangeRecord cr; try { int result; while ((cr = reader.readChangeRecord()) != null) while (reader.hasNext()) { result = cr.accept(visitor, null); final ChangeRecord cr = reader.readChangeRecord(); final int result = cr.accept(visitor, null); if (result != 0 && !continueOnError.isPresent()) { return result; sdk/src/org/opends/sdk/ldif/AbstractLDIFReader.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2009 Sun Microsystems, Inc. * Copyright 2009-2010 Sun Microsystems, Inc. */ package org.opends.sdk.ldif; @@ -141,9 +141,12 @@ */ public void close() throws IOException { if (reader != null) { reader.close(); reader = null; } } sdk/src/org/opends/sdk/ldif/ChangeRecordReader.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2009 Sun Microsystems, Inc. * Copyright 2009-2010 Sun Microsystems, Inc. */ package org.opends.sdk.ldif; @@ -31,8 +31,7 @@ import java.io.Closeable; import java.io.IOException; import org.opends.sdk.DecodeException; import java.util.NoSuchElementException; @@ -46,10 +45,6 @@ * malformed change records and, if it is possible, how they are handled. * <li>Any synchronization limitations. * </ul> * <p> * TODO: LDIFInputStreamReader * <p> * TODO: SearchResultEntryReader */ public interface ChangeRecordReader extends Closeable { @@ -62,23 +57,35 @@ * @throws IOException * If an unexpected IO error occurred while closing. */ @Override void close() throws IOException; /** * Returns {@code true} if this reader contains another change record, * blocking if necessary until either the next change record is available or * the end of the stream is reached. * * @return {@code true} if this reader contains another change record. * @throws IOException * If an unexpected IO error occurred. */ boolean hasNext() throws IOException; /** * Reads the next change record, blocking if necessary until a change record * is available. If the next change record does not contain a change type then * it will be treated as an {@code Add} change record. * * @return The next change record, or {@code null} if there are no more change * records to be read. * @throws DecodeException * If the change record could not be decoded because it was * malformed. * @return The next change record. * @throws IOException * If an unexpected IO error occurred while reading the change * record. * @throws NoSuchElementException * If this reader does not contain any more change records. */ ChangeRecord readChangeRecord() throws DecodeException, IOException; ChangeRecord readChangeRecord() throws IOException, NoSuchElementException; } sdk/src/org/opends/sdk/ldif/ConnectionEntryReader.java
@@ -30,6 +30,7 @@ import java.io.InterruptedIOException; import java.util.NoSuchElementException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -60,21 +61,29 @@ * * <pre> * Connection connection = ...; * ConnectionEntryReader results = connection.search( * "dc=example,dc=com", * SearchScope.WHOLE_SUBTREE, * "(objectClass=person)"); * SearchResultEntry entry; * ConnectionEntryReader results = connection.search("dc=example,dc=com", * SearchScope.WHOLE_SUBTREE, "(objectClass=person)"); * try * { * while ((entry = results.readEntry()) != null) * while (reader.hasNext()) * { * // Process search result entry. * if (!reader.isReference()) * { * SearchResultEntry entry = reader.readEntry(); * * // Handle entry... * } * else * { * SearchResultReference ref = reader.readReference(); * * // Handle continuation reference... * } * } * catch (Exception e) * } * catch (IOException e) * { * // Handle exceptions * // Handle exceptions... * } * finally * { @@ -181,6 +190,7 @@ private final BufferHandler buffer; private final FutureResult<Result> future; private Response nextResponse = null; @@ -242,65 +252,69 @@ /** * Returns the next search result entry contained in the search results, * waiting if necessary until one becomes available. * * @return The next search result entry, or {@code null} if there are no more * entries in the search results. * @throws SearchResultReferenceIOException * If the next search response was a search result reference. This * connection entry reader may still contain remaining search * results and references which can be retrieved using additional * calls to this method. * @throws ErrorResultIOException * If the result code indicates that the search operation failed for * some reason. * @throws InterruptedIOException * If the current thread was interrupted while waiting. * {@inheritDoc} */ @Override public SearchResultEntry readEntry() throws SearchResultReferenceIOException, ErrorResultIOException, InterruptedIOException public boolean hasNext() throws ErrorResultIOException, InterruptedIOException { Response r; try // Poll for the next response if needed. final Response r = getNextResponse(); if (!(r instanceof Result)) { while ((r = buffer.responses.poll(50, TimeUnit.MILLISECONDS)) == null) { if (buffer.isInterrupted) { // The worker thread processing the result was interrupted so no // result will ever arrive. We don't want to hang this thread forever // while we wait, so terminate now. r = Responses.newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR); break; } } } catch (final InterruptedException e) { throw new InterruptedIOException(e.getMessage()); // Entry or reference. return true; } if (r instanceof SearchResultEntry) { return (SearchResultEntry) r; } else if (r instanceof SearchResultReference) { throw new SearchResultReferenceIOException((SearchResultReference) r); } else if (r instanceof Result) { // Final result. final Result result = (Result) r; if (result.isSuccess()) { return null; return false; } else final ErrorResultException e = ErrorResultException.wrap(result); throw new ErrorResultIOException(e); } /** * Waits for the next search result entry or reference to become available and * returns {@code true} if it is a reference, or {@code false} if it is an * entry. * * @return {@code true} if the next search result is a reference, or * {@code false} if it is an entry. * @throws ErrorResultIOException * If there are no more search result entries or references and the * search result code indicates that the search operation failed for * some reason. * @throws InterruptedIOException * If the current thread was interrupted while waiting. * @throws NoSuchElementException * If there are no more search result entries or references and the * search result code indicates that the search operation succeeded. */ public boolean isReference() throws ErrorResultIOException, InterruptedIOException, NoSuchElementException { throw new ErrorResultIOException(ErrorResultException.wrap(result)); // Throws ErrorResultIOException if search returned error. if (!hasNext()) { // Search has completed successfully. throw new NoSuchElementException(); } // Entry or reference. final Response r = nextResponse; if (r instanceof SearchResultEntry) { return false; } else if (r instanceof SearchResultReference) { return true; } else { @@ -308,4 +322,108 @@ + r.getClass().toString()); } } /** * Waits for the next search result entry or reference to become available * and, if it is an entry, returns it as a {@code SearchResultEntry}. If the * next search response is a reference then this method will throw a * {@code SearchResultReferenceIOException}. * * @return The next search result entry. * @throws SearchResultReferenceIOException * If the next search response was a search result reference. This * connection entry reader may still contain remaining search * results and references which can be retrieved using additional * calls to this method. * @throws ErrorResultIOException * If there are no more search result entries or references and the * search result code indicates that the search operation failed for * some reason. * @throws InterruptedIOException * If the current thread was interrupted while waiting. * @throws NoSuchElementException * If there are no more search result entries or references and the * search result code indicates that the search operation succeeded. */ @Override public SearchResultEntry readEntry() throws SearchResultReferenceIOException, ErrorResultIOException, InterruptedIOException, NoSuchElementException { if (!isReference()) { final SearchResultEntry entry = (SearchResultEntry) nextResponse; nextResponse = null; return entry; } else { final SearchResultReference reference = (SearchResultReference) nextResponse; nextResponse = null; throw new SearchResultReferenceIOException(reference); } } /** * Waits for the next search result entry or reference to become available * and, if it is a reference, returns it as a {@code SearchResultReference}. * If the next search response is an entry then this method will return * {@code null}. * * @return The next search result reference, or {@code null} if the next * response was a search result entry. * @throws ErrorResultIOException * If there are no more search result entries or references and the * search result code indicates that the search operation failed for * some reason. * @throws InterruptedIOException * If the current thread was interrupted while waiting. * @throws NoSuchElementException * If there are no more search result entries or references and the * search result code indicates that the search operation succeeded. */ public SearchResultReference readReference() throws ErrorResultIOException, InterruptedIOException, NoSuchElementException { if (isReference()) { final SearchResultReference reference = (SearchResultReference) nextResponse; nextResponse = null; return reference; } else { return null; } } private Response getNextResponse() throws InterruptedIOException { while (nextResponse == null) { try { nextResponse = buffer.responses.poll(50, TimeUnit.MILLISECONDS); } catch (final InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } if (nextResponse == null && buffer.isInterrupted) { // The worker thread processing the result was interrupted so no // result will ever arrive. We don't want to hang this thread // forever while we wait, so terminate now. nextResponse = Responses.newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR); break; } } return nextResponse; } } sdk/src/org/opends/sdk/ldif/EntryReader.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2009 Sun Microsystems, Inc. * Copyright 2009-2010 Sun Microsystems, Inc. */ package org.opends.sdk.ldif; @@ -31,8 +31,8 @@ import java.io.Closeable; import java.io.IOException; import java.util.NoSuchElementException; import org.opends.sdk.DecodeException; import org.opends.sdk.Entry; @@ -46,10 +46,6 @@ * malformed change records and, if it is possible, how they are handled. * <li>Any synchronization limitations. * </ul> * <p> * TODO: LDIFInputStreamReader * <p> * TODO: SearchResultEntryReader */ public interface EntryReader extends Closeable { @@ -62,19 +58,32 @@ * @throws IOException * If an unexpected IO error occurred while closing. */ @Override void close() throws IOException; /** * Returns {@code true} if this reader contains another entry, blocking if * necessary until either the next entry is available or the end of the stream * is reached. * * @return {@code true} if this reader contains another entry. * @throws IOException * If an unexpected IO error occurred. */ boolean hasNext() throws IOException; /** * Reads the next entry, blocking if necessary until an entry is available. * * @return The next entry or {@code null} if there are no more entries to be * read. * @throws DecodeException * If the entry could not be decoded because it was malformed. * @return The next entry. * @throws IOException * If an unexpected IO error occurred while reading the entry. * @throws NoSuchElementException * If this reader does not contain any more entries. */ Entry readEntry() throws DecodeException, IOException; Entry readEntry() throws IOException, NoSuchElementException; } sdk/src/org/opends/sdk/ldif/LDIFChangeRecordReader.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2009 Sun Microsystems, Inc. * Copyright 2009-2010 Sun Microsystems, Inc. */ package org.opends.sdk.ldif; @@ -37,6 +37,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import org.opends.sdk.*; import org.opends.sdk.requests.ModifyDNRequest; @@ -79,9 +80,7 @@ final LDIFChangeRecordReader reader = new LDIFChangeRecordReader(ldifLines); try { final ChangeRecord record = reader.readChangeRecord(); if (record == null) if (!reader.hasNext()) { // No change record found. final LocalizableMessage message = WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND @@ -89,7 +88,9 @@ throw new LocalizedIllegalArgumentException(message); } if (reader.readChangeRecord() != null) final ChangeRecord record = reader.readChangeRecord(); if (reader.hasNext()) { // Multiple change records found. final LocalizableMessage message = WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND @@ -115,6 +116,13 @@ private ChangeRecord nextChangeRecord = null; // Poison used to indicate end of LDIF. private static final ChangeRecord EOF = Requests.newAddRequest(DN.rootDN()); /** * Creates a new LDIF change record reader whose source is the provided input * stream. @@ -169,6 +177,7 @@ /** * {@inheritDoc} */ @Override public void close() throws IOException { close0(); @@ -178,111 +187,38 @@ /** * {@inheritDoc} * * @throws DecodeException * If the change record could not be decoded because it was * malformed. */ @Override public boolean hasNext() throws DecodeException, IOException { return getNextChangeRecord() != EOF; } /** * {@inheritDoc} * * @throws DecodeException * If the entry could not be decoded because it was malformed. */ @Override public ChangeRecord readChangeRecord() throws DecodeException, IOException { // Continue until an unfiltered entry is obtained. while (true) if (!hasNext()) { LDIFRecord record = null; // Read the set of lines that make up the next entry. record = readLDIFRecord(); if (record == null) { return null; // LDIF reader has completed successfully. throw new NoSuchElementException(); } // Read the DN of the entry and see if it is one that should be // included in the import. DN entryDN; try { entryDN = readLDIFRecordDN(record); if (entryDN == null) { // Skip version record. continue; } } catch (final DecodeException e) { rejectLDIFRecord(record, e.getMessageObject()); continue; } // Skip if branch containing the entry DN is excluded. if (isBranchExcluded(entryDN)) { final LocalizableMessage message = LocalizableMessage .raw("Skipping entry because it is in excluded branch"); skipLDIFRecord(record, message); continue; } ChangeRecord changeRecord = null; try { if (!record.iterator.hasNext()) { // FIXME: improve error. final LocalizableMessage message = LocalizableMessage .raw("Missing changetype"); throw DecodeException.error(message); } final KeyValuePair pair = new KeyValuePair(); final String ldifLine = readLDIFRecordKeyValuePair(record, pair, false); if (!toLowerCase(pair.key).equals("changetype")) { // Default to add change record. changeRecord = parseAddChangeRecordEntry(entryDN, ldifLine, record); } else { final String changeType = toLowerCase(pair.value); if (changeType.equals("add")) { changeRecord = parseAddChangeRecordEntry(entryDN, null, record); } else if (changeType.equals("delete")) { changeRecord = parseDeleteChangeRecordEntry(entryDN, record); } else if (changeType.equals("modify")) { changeRecord = parseModifyChangeRecordEntry(entryDN, record); } else if (changeType.equals("modrdn")) { changeRecord = parseModifyDNChangeRecordEntry(entryDN, record); } else if (changeType.equals("moddn")) { changeRecord = parseModifyDNChangeRecordEntry(entryDN, record); } else { // FIXME: improve error. final LocalizableMessage message = ERR_LDIF_INVALID_CHANGETYPE_ATTRIBUTE .get(pair.value, "add, delete, modify, moddn, modrdn"); throw DecodeException.error(message); } } } catch (final DecodeException e) { rejectLDIFRecord(record, e.getMessageObject()); continue; } if (changeRecord != null) { final ChangeRecord changeRecord = nextChangeRecord; nextChangeRecord = null; return changeRecord; } } } @@ -309,8 +245,8 @@ * change records that are read from LDIF. The default is {@code false}. * * @param excludeUserAttributes * {@code true} if all user attributes should be excluded, or {@code * false} otherwise. * {@code true} if all user attributes should be excluded, or * {@code false} otherwise. * @return A reference to this {@code LDIFChangeRecordReader}. */ public LDIFChangeRecordReader setExcludeAllUserAttributes( @@ -418,8 +354,8 @@ * records that are read from LDIF. The default is {@code true} . * * @param validateSchema * {@code true} if schema validation should be performed, or {@code * false} otherwise. * {@code true} if schema validation should be performed, or * {@code false} otherwise. * @return A reference to this {@code LDIFChangeRecordReader}. */ public LDIFChangeRecordReader setValidateSchema(final boolean validateSchema) @@ -430,6 +366,115 @@ private ChangeRecord getNextChangeRecord() throws DecodeException, IOException { while (nextChangeRecord == null) { LDIFRecord record = null; // Read the set of lines that make up the next entry. record = readLDIFRecord(); if (record == null) { nextChangeRecord = EOF; break; } // Read the DN of the entry and see if it is one that should be // included in the import. DN entryDN; try { entryDN = readLDIFRecordDN(record); if (entryDN == null) { // Skip version record. continue; } } catch (final DecodeException e) { rejectLDIFRecord(record, e.getMessageObject()); continue; } // Skip if branch containing the entry DN is excluded. if (isBranchExcluded(entryDN)) { final LocalizableMessage message = LocalizableMessage .raw("Skipping entry because it is in excluded branch"); skipLDIFRecord(record, message); continue; } ChangeRecord changeRecord = null; try { if (!record.iterator.hasNext()) { // FIXME: improve error. final LocalizableMessage message = LocalizableMessage .raw("Missing changetype"); throw DecodeException.error(message); } final KeyValuePair pair = new KeyValuePair(); final String ldifLine = readLDIFRecordKeyValuePair(record, pair, false); if (!toLowerCase(pair.key).equals("changetype")) { // Default to add change record. changeRecord = parseAddChangeRecordEntry(entryDN, ldifLine, record); } else { final String changeType = toLowerCase(pair.value); if (changeType.equals("add")) { changeRecord = parseAddChangeRecordEntry(entryDN, null, record); } else if (changeType.equals("delete")) { changeRecord = parseDeleteChangeRecordEntry(entryDN, record); } else if (changeType.equals("modify")) { changeRecord = parseModifyChangeRecordEntry(entryDN, record); } else if (changeType.equals("modrdn")) { changeRecord = parseModifyDNChangeRecordEntry(entryDN, record); } else if (changeType.equals("moddn")) { changeRecord = parseModifyDNChangeRecordEntry(entryDN, record); } else { // FIXME: improve error. final LocalizableMessage message = ERR_LDIF_INVALID_CHANGETYPE_ATTRIBUTE .get(pair.value, "add, delete, modify, moddn, modrdn"); throw DecodeException.error(message); } } } catch (final DecodeException e) { rejectLDIFRecord(record, e.getMessageObject()); continue; } if (changeRecord != null) { nextChangeRecord = changeRecord; } } return nextChangeRecord; } private ChangeRecord parseAddChangeRecordEntry(final DN entryDN, final String lastLDIFLine, final LDIFRecord record) throws DecodeException @@ -581,8 +626,8 @@ { // TODO: include line number. final LocalizableMessage message = ERR_LDIF_INVALID_CHANGERECORD_ATTRIBUTE .get(attributeDescription2.toString(), attributeDescription .toString()); .get(attributeDescription2.toString(), attributeDescription.toString()); throw DecodeException.error(message); } sdk/src/org/opends/sdk/ldif/LDIFEntryReader.java
@@ -22,24 +22,20 @@ * CDDL HEADER END * * * Copyright 2009 Sun Microsystems, Inc. * Copyright 2009-2010 Sun Microsystems, Inc. */ package org.opends.sdk.ldif; import static com.sun.opends.sdk.messages.Messages. WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND; import static com.sun.opends.sdk.messages.Messages. WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND; import static com.sun.opends.sdk.messages.Messages. WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR; import static com.sun.opends.sdk.messages.Messages.*; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import org.opends.sdk.*; import org.opends.sdk.schema.Schema; @@ -58,6 +54,11 @@ public final class LDIFEntryReader extends AbstractLDIFReader implements EntryReader { // Poison used to indicate end of LDIF. private static final Entry EOF = new LinkedHashMapEntry(); /** * Parses the provided array of LDIF lines as a single LDIF entry. * @@ -77,9 +78,7 @@ final LDIFEntryReader reader = new LDIFEntryReader(ldifLines); try { final Entry entry = reader.readEntry(); if (entry == null) if (!reader.hasNext()) { // No change record found. final LocalizableMessage message = WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND @@ -87,7 +86,9 @@ throw new LocalizedIllegalArgumentException(message); } if (reader.readEntry() != null) final Entry entry = reader.readEntry(); if (reader.hasNext()) { // Multiple change records found. final LocalizableMessage message = WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND @@ -113,6 +114,10 @@ private Entry nextEntry = null; /** * Creates a new LDIF entry reader whose source is the provided input stream. * @@ -164,6 +169,7 @@ /** * {@inheritDoc} */ @Override public void close() throws IOException { close0(); @@ -173,76 +179,37 @@ /** * {@inheritDoc} * * @throws DecodeException * If the entry could not be decoded because it was malformed. */ @Override public boolean hasNext() throws DecodeException, IOException { return getNextEntry() != EOF; } /** * {@inheritDoc} * * @throws DecodeException * If the entry could not be decoded because it was malformed. */ @Override public Entry readEntry() throws DecodeException, IOException { // Continue until an unfiltered entry is obtained. while (true) if (!hasNext()) { LDIFRecord record = null; // Read the set of lines that make up the next entry. record = readLDIFRecord(); if (record == null) { return null; // LDIF reader has completed successfully. throw new NoSuchElementException(); } // Read the DN of the entry and see if it is one that should be // included in the import. DN entryDN; try { entryDN = readLDIFRecordDN(record); if (entryDN == null) { // Skip version record. continue; } } catch (final DecodeException e) { rejectLDIFRecord(record, e.getMessageObject()); continue; } // Skip if branch containing the entry DN is excluded. if (isBranchExcluded(entryDN)) { final LocalizableMessage message = LocalizableMessage .raw("Skipping entry because it is in excluded branch"); skipLDIFRecord(record, message); continue; } // Use an Entry for the AttributeSequence. final Entry entry = new LinkedHashMapEntry(entryDN); try { while (record.iterator.hasNext()) { final String ldifLine = record.iterator.next(); readLDIFRecordAttributeValue(record, ldifLine, entry); } } catch (final DecodeException e) { rejectLDIFRecord(record, e.getMessageObject()); continue; } // Skip if the entry is excluded by any filters. if (isEntryExcluded(entry)) { final LocalizableMessage message = LocalizableMessage .raw("Skipping entry due to exclusing filters"); skipLDIFRecord(record, message); continue; } final Entry entry = nextEntry; nextEntry = null; return entry; } } @@ -269,8 +236,8 @@ * entries that are read from LDIF. The default is {@code false}. * * @param excludeUserAttributes * {@code true} if all user attributes should be excluded, or {@code * false} otherwise. * {@code true} if all user attributes should be excluded, or * {@code false} otherwise. * @return A reference to this {@code LDIFEntryReader}. */ public LDIFEntryReader setExcludeAllUserAttributes( @@ -414,8 +381,8 @@ * that are read from LDIF. The default is {@code true}. * * @param validateSchema * {@code true} if schema validation should be performed, or {@code * false} otherwise. * {@code true} if schema validation should be performed, or * {@code false} otherwise. * @return A reference to this {@code LDIFEntryReader}. */ public LDIFEntryReader setValidateSchema(final boolean validateSchema) @@ -424,4 +391,78 @@ return this; } private Entry getNextEntry() throws DecodeException, IOException { while (nextEntry == null) { LDIFRecord record = null; // Read the set of lines that make up the next entry. record = readLDIFRecord(); if (record == null) { nextEntry = EOF; break; } // Read the DN of the entry and see if it is one that should be // included in the import. DN entryDN; try { entryDN = readLDIFRecordDN(record); if (entryDN == null) { // Skip version record. continue; } } catch (final DecodeException e) { rejectLDIFRecord(record, e.getMessageObject()); continue; } // Skip if branch containing the entry DN is excluded. if (isBranchExcluded(entryDN)) { final LocalizableMessage message = LocalizableMessage .raw("Skipping entry because it is in excluded branch"); skipLDIFRecord(record, message); continue; } // Use an Entry for the AttributeSequence. final Entry entry = new LinkedHashMapEntry(entryDN); try { while (record.iterator.hasNext()) { final String ldifLine = record.iterator.next(); readLDIFRecordAttributeValue(record, ldifLine, entry); } } catch (final DecodeException e) { rejectLDIFRecord(record, e.getMessageObject()); continue; } // Skip if the entry is excluded by any filters. if (isEntryExcluded(entry)) { final LocalizableMessage message = LocalizableMessage .raw("Skipping entry due to exclusing filters"); skipLDIFRecord(record, message); continue; } nextEntry = entry; } return nextEntry; } } sdk/tests/unit-tests-testng/src/org/opends/sdk/SynchronousConnectionTestCase.java
@@ -29,17 +29,18 @@ import static org.testng.Assert.assertNull; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import java.util.List; import java.util.NoSuchElementException; import org.opends.sdk.ldif.EntryReader; import org.opends.sdk.ldif.ConnectionEntryReader; import org.opends.sdk.requests.Requests; import org.opends.sdk.responses.BindResult; import org.opends.sdk.responses.CompareResult; import org.opends.sdk.responses.Result; import org.opends.sdk.responses.SearchResultEntry; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -155,11 +156,27 @@ public void testSearchRequest() throws Exception { final SynchronousConnection con = new SynchronousConnection(asyncCon); final EntryReader reader = con.search( final ConnectionEntryReader reader = con.search( "uid=user.0,ou=people,o=test", SearchScope.BASE_OBJECT, "objectclass=*", "cn"); Assert.assertTrue(reader.hasNext()); Assert.assertFalse(reader.isReference()); Assert.assertTrue(reader.hasNext()); SearchResultEntry entry = reader.readEntry(); Assert.assertEquals(entry.getName(), DN.valueOf("uid=user.0,ou=people,o=test")); Assert.assertFalse(reader.hasNext()); try { reader.readEntry(); assertNull(reader.readEntry()); Assert .fail("reader.readEntry() should have thrown NoSuchElementException"); } catch (NoSuchElementException e) { // This is expected. } Assert.assertFalse(reader.hasNext()); } // TODO: add more tests. } sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryReaderTestCase.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2009 Sun Microsystems, Inc. * Copyright 2009-2010 Sun Microsystems, Inc. */ package org.opends.sdk.ldif; @@ -32,9 +32,12 @@ import static org.testng.Assert.assertNotNull; import java.io.FileInputStream; import java.util.NoSuchElementException; import org.opends.sdk.AbstractEntry; import org.opends.sdk.DN; import org.opends.sdk.Entry; import org.opends.sdk.TestCaseUtils; import org.testng.Assert; import org.testng.annotations.Test; @@ -52,6 +55,45 @@ * If the test failed unexpectedly. */ @Test() public void testEmpty() throws Exception { final String path = TestCaseUtils.createTempFile(""); final FileInputStream in = new FileInputStream(path); final LDIFEntryReader reader = new LDIFEntryReader(in); try { reader.setValidateSchema(false); Assert.assertFalse(reader.hasNext()); Assert.assertFalse(reader.hasNext()); try { reader.readEntry(); Assert .fail("reader.readEntry() should have thrown NoSuchElementException"); } catch (NoSuchElementException e) { // This is expected. } Assert.assertFalse(reader.hasNext()); } finally { reader.close(); } } /** * Tests readEntry method of LDIFEntryReader class.See * https://opends.dev.java.net/issues/show_bug.cgi?id=4545 for more details. * * @throws Exception * If the test failed unexpectedly. */ @Test() public void testReadEntry() throws Exception { final String path = TestCaseUtils @@ -80,9 +122,31 @@ "postalAddress: Aaccf Amar$01251 Chestnut Street$Panama City, DE 50369", "description: This is the description for Aaccf Amar."); final FileInputStream in = new FileInputStream(path); final LDIFEntryReader entryReader = new LDIFEntryReader(in); entryReader.setValidateSchema(false); final AbstractEntry entry = (AbstractEntry) entryReader.readEntry(); final LDIFEntryReader reader = new LDIFEntryReader(in); try { reader.setValidateSchema(false); Assert.assertTrue(reader.hasNext()); final Entry entry = reader.readEntry(); assertNotNull(entry); Assert.assertEquals(entry.getName(), DN.valueOf("uid=1,ou=people,dc=ucsf,dc=edu")); Assert.assertFalse(reader.hasNext()); try { reader.readEntry(); Assert .fail("reader.readEntry() should have thrown NoSuchElementException"); } catch (NoSuchElementException e) { // This is expected. } } finally { reader.close(); } } }