001/*
002 * Copyright 2009-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2009-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldif;
022
023
024
025import java.util.concurrent.atomic.AtomicBoolean;
026
027import com.unboundid.ldap.sdk.Entry;
028import com.unboundid.ldap.sdk.EntrySource;
029import com.unboundid.ldap.sdk.EntrySourceException;
030import com.unboundid.util.Debug;
031import com.unboundid.util.ThreadSafety;
032import com.unboundid.util.ThreadSafetyLevel;
033import com.unboundid.util.Validator;
034
035
036
037/**
038 * This class provides an {@link EntrySource} that will read entries from an
039 * LDIF file.
040 * <BR><BR>
041 * <H2>Example</H2>
042 * The following example demonstrates the process that may be used for iterating
043 * through all entries in an LDIF file using the entry source API:
044 * <PRE>
045 * LDIFEntrySource entrySource =
046 *      new LDIFEntrySource(new LDIFReader(pathToLDIFFile));
047 *
048 * int entriesRead = 0;
049 * int errorsEncountered = 0;
050 * try
051 * {
052 *   while (true)
053 *   {
054 *     try
055 *     {
056 *       Entry entry = entrySource.nextEntry();
057 *       if (entry == null)
058 *       {
059 *         // There are no more entries to be read.
060 *         break;
061 *       }
062 *       else
063 *       {
064 *         // Do something with the entry here.
065 *         entriesRead++;
066 *       }
067 *     }
068 *     catch (EntrySourceException e)
069 *     {
070 *       // Some kind of problem was encountered (e.g., a malformed entry
071 *       // found in the LDIF file, or an I/O error when trying to read).  See
072 *       // if we can continue reading entries.
073 *       errorsEncountered++;
074 *       if (! e.mayContinueReading())
075 *       {
076 *         break;
077 *       }
078 *     }
079 *   }
080 * }
081 * finally
082 * {
083 *   entrySource.close();
084 * }
085 * </PRE>
086 */
087@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
088public final class LDIFEntrySource
089       extends EntrySource
090{
091  // Indicates whether this entry source has been closed.
092  private final AtomicBoolean closed;
093
094  // The LDIF reader from which entries will be read.
095  private final LDIFReader ldifReader;
096
097
098
099  /**
100   * Creates a new LDAP entry source that will obtain entries from the provided
101   * LDIF reader.
102   *
103   * @param  ldifReader  The LDIF reader from which to read entries.  It must
104   *                     not be {@code null}.
105   */
106  public LDIFEntrySource(final LDIFReader ldifReader)
107  {
108    Validator.ensureNotNull(ldifReader);
109
110    this.ldifReader = ldifReader;
111
112    closed = new AtomicBoolean(false);
113  }
114
115
116
117  /**
118   * {@inheritDoc}
119   */
120  @Override()
121  public Entry nextEntry()
122         throws EntrySourceException
123  {
124    if (closed.get())
125    {
126      return null;
127    }
128
129    try
130    {
131      final Entry e = ldifReader.readEntry();
132      if (e == null)
133      {
134        close();
135      }
136
137      return e;
138    }
139    catch (final LDIFException le)
140    {
141      Debug.debugException(le);
142      if (le.mayContinueReading())
143      {
144        throw new EntrySourceException(true, le);
145      }
146      else
147      {
148        close();
149        throw new EntrySourceException(false, le);
150      }
151    }
152    catch (final Exception e)
153    {
154      Debug.debugException(e);
155      close();
156      throw new EntrySourceException(false, e);
157    }
158  }
159
160
161
162  /**
163   * {@inheritDoc}
164   */
165  @Override()
166  public void close()
167  {
168    if (closed.compareAndSet(false, true))
169    {
170      try
171      {
172        ldifReader.close();
173      }
174      catch (final Exception e)
175      {
176        Debug.debugException(e);
177      }
178    }
179  }
180}