001    /*
002     * Copyright 2010-2013 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2010-2013 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     */
021    package com.unboundid.ldap.sdk;
022    
023    
024    
025    import java.util.Arrays;
026    import java.util.Collection;
027    import java.util.Iterator;
028    
029    import com.unboundid.util.ThreadSafety;
030    import com.unboundid.util.ThreadSafetyLevel;
031    
032    import static com.unboundid.ldap.sdk.LDAPMessages.*;
033    import static com.unboundid.util.Debug.*;
034    import static com.unboundid.util.StaticUtils.*;
035    import static com.unboundid.util.Validator.*;
036    
037    
038    
039    /**
040     * This class provides an {@link EntrySource} that will retrieve entries
041     * referenced by a provided set of DNs.  The connection will remain open after
042     * all entries have been read.
043     * <BR><BR>
044     * It is not necessary to close this entry source when it is no longer needed,
045     * although there is no cost or penalty in doing so.  Any exceptions thrown by
046     * the {@link #nextEntry()} method will have the {@code mayContinueReading}
047     * value set to {@code true}.
048     * <H2>Example</H2>
049     * The following example demonstrates the process for retrieving a static group
050     * entry and using a {@code DNEntrySource} to iterate across the members of that
051     * group:
052     * <PRE>
053     *   Entry groupEntry =
054     *        connection.getEntry("cn=My Group,ou=Groups,dc=example,dc=com");
055     *   String[] memberValues = groupEntry.getAttributeValues("member");
056     *   if (memberValues != null)
057     *   {
058     *     DNEntrySource entrySource =
059     *          new DNEntrySource(connection, memberValues, "cn");
060     *     while (true)
061     *     {
062     *       Entry memberEntry = entrySource.nextEntry();
063     *       if (memberEntry == null)
064     *       {
065     *         break;
066     *       }
067     *
068     *       System.out.println("Retrieved member entry:  " +
069     *            memberEntry.getAttributeValue("cn"));
070     *     }
071     *   }
072     * </PRE>
073     */
074    @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
075    public final class DNEntrySource
076           extends EntrySource
077    {
078      // The iterator to use to access the DNs.  It will either be across DN or
079      // String objects.
080      private final Iterator<?> dnIterator;
081    
082      // The connection to use to communicate with the directory server.
083      private final LDAPInterface connection;
084    
085      // The set of attributes to include in entries that are returned.
086      private final String[] attributes;
087    
088    
089    
090      /**
091       * Creates a new DN entry source with the provided information.
092       *
093       * @param  connection  The connection to the directory server from which the
094       *                     entries will be read.  It must not be {@code null}.
095       * @param  dns         The set of DNs to be read.  It must not be
096       *                     {@code null}.
097       * @param  attributes  The set of attributes to include in entries that are
098       *                     returned.  If this is empty or {@code null}, then all
099       *                     user attributes will be requested.
100       */
101      public DNEntrySource(final LDAPInterface connection, final DN[] dns,
102                           final String... attributes)
103      {
104        ensureNotNull(connection, dns);
105    
106        this.connection = connection;
107        dnIterator = Arrays.asList(dns).iterator();
108    
109        if (attributes == null)
110        {
111          this.attributes = NO_STRINGS;
112        }
113        else
114        {
115          this.attributes = attributes;
116        }
117      }
118    
119    
120    
121      /**
122       * Creates a new DN entry source with the provided information.
123       *
124       * @param  connection  The connection to the directory server from which the
125       *                     entries will be read.  It must not be {@code null}.
126       * @param  dns         The set of DNs to be read.  It must not be
127       *                     {@code null}.
128       * @param  attributes  The set of attributes to include in entries that are
129       *                     returned.  If this is empty or {@code null}, then all
130       *                     user attributes will be requested.
131       */
132      public DNEntrySource(final LDAPInterface connection, final String[] dns,
133                           final String... attributes)
134      {
135        this(connection, Arrays.asList(dns), attributes);
136      }
137    
138    
139    
140      /**
141       * Creates a new DN entry source with the provided information.
142       *
143       * @param  connection  The connection to the directory server from which the
144       *                     entries will be read.  It must not be {@code null}.
145       * @param  dns         The set of DNs to be read.  It must not be
146       *                     {@code null}.
147       * @param  attributes  The set of attributes to include in entries that are
148       *                     returned.  If this is empty or {@code null}, then all
149       *                     user attributes will be requested.
150       */
151      public DNEntrySource(final LDAPInterface connection,
152                           final Collection<String> dns, final String... attributes)
153      {
154        ensureNotNull(connection, dns);
155    
156        this.connection = connection;
157        dnIterator = dns.iterator();
158    
159        if (attributes == null)
160        {
161          this.attributes = NO_STRINGS;
162        }
163        else
164        {
165          this.attributes = attributes;
166        }
167      }
168    
169    
170    
171      /**
172       * {@inheritDoc}
173       */
174      @Override()
175      public Entry nextEntry()
176             throws EntrySourceException
177      {
178        if (! dnIterator.hasNext())
179        {
180          return null;
181        }
182    
183        final String dn = String.valueOf(dnIterator.next());
184        try
185        {
186          final Entry e = connection.getEntry(dn, attributes);
187          if (e == null)
188          {
189            throw new EntrySourceException(true,
190                 ERR_DN_ENTRY_SOURCE_NO_SUCH_ENTRY.get(dn),
191                 new LDAPException(ResultCode.NO_RESULTS_RETURNED));
192          }
193          else
194          {
195            return e;
196          }
197        }
198        catch (final LDAPException le)
199        {
200          debugException(le);
201          throw new EntrySourceException(true,
202               ERR_DN_ENTRY_SOURCE_ERR_RETRIEVING_ENTRY.get(dn,
203                    getExceptionMessage(le)),
204               le);
205        }
206      }
207    
208    
209    
210      /**
211       * {@inheritDoc}
212       */
213      @Override()
214      public void close()
215      {
216        // No implementation is required.
217      }
218    }