001/*
002 * Copyright 2009-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2009-2014 UnboundID Corp.
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.ThreadSafety;
031import com.unboundid.util.ThreadSafetyLevel;
032
033import static com.unboundid.util.Debug.*;
034import static com.unboundid.util.Validator.*;
035
036
037
038/**
039 * This class provides an {@link EntrySource} that will read entries from an
040 * LDIF file.
041 * <BR><BR>
042 * <H2>Example</H2>
043 * The following example demonstrates the process that may be used for iterating
044 * through all entries in an LDIF file using the entry source API:
045 * <PRE>
046 * LDIFEntrySource entrySource =
047 *      new LDIFEntrySource(new LDIFReader(pathToLDIFFile));
048 *
049 * int entriesRead = 0;
050 * int errorsEncountered = 0;
051 * try
052 * {
053 *   while (true)
054 *   {
055 *     try
056 *     {
057 *       Entry entry = entrySource.nextEntry();
058 *       if (entry == null)
059 *       {
060 *         // There are no more entries to be read.
061 *         break;
062 *       }
063 *       else
064 *       {
065 *         // Do something with the entry here.
066 *         entriesRead++;
067 *       }
068 *     }
069 *     catch (EntrySourceException e)
070 *     {
071 *       // Some kind of problem was encountered (e.g., a malformed entry
072 *       // found in the LDIF file, or an I/O error when trying to read).  See
073 *       // if we can continue reading entries.
074 *       errorsEncountered++;
075 *       if (! e.mayContinueReading())
076 *       {
077 *         break;
078 *       }
079 *     }
080 *   }
081 * }
082 * finally
083 * {
084 *   entrySource.close();
085 * }
086 * </PRE>
087 */
088@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
089public final class LDIFEntrySource
090       extends EntrySource
091{
092  // Indicates whether this entry source has been closed.
093  private final AtomicBoolean closed;
094
095  // The LDIF reader from which entries will be read.
096  private final LDIFReader ldifReader;
097
098
099
100  /**
101   * Creates a new LDAP entry source that will obtain entries from the provided
102   * LDIF reader.
103   *
104   * @param  ldifReader  The LDIF reader from which to read entries.  It must
105   *                     not be {@code null}.
106   */
107  public LDIFEntrySource(final LDIFReader ldifReader)
108  {
109    ensureNotNull(ldifReader);
110
111    this.ldifReader = ldifReader;
112
113    closed = new AtomicBoolean(false);
114  }
115
116
117
118  /**
119   * {@inheritDoc}
120   */
121  @Override()
122  public Entry nextEntry()
123         throws EntrySourceException
124  {
125    if (closed.get())
126    {
127      return null;
128    }
129
130    try
131    {
132      final Entry e = ldifReader.readEntry();
133      if (e == null)
134      {
135        close();
136      }
137
138      return e;
139    }
140    catch (LDIFException le)
141    {
142      debugException(le);
143      if (le.mayContinueReading())
144      {
145        throw new EntrySourceException(true, le);
146      }
147      else
148      {
149        close();
150        throw new EntrySourceException(false, le);
151      }
152    }
153    catch (Exception e)
154    {
155      debugException(e);
156      close();
157      throw new EntrySourceException(false, e);
158    }
159  }
160
161
162
163  /**
164   * {@inheritDoc}
165   */
166  @Override()
167  public void close()
168  {
169    if (closed.compareAndSet(false, true))
170    {
171      try
172      {
173        ldifReader.close();
174      }
175      catch (Exception e)
176      {
177        debugException(e);
178      }
179    }
180  }
181}