001 /*
002 * Copyright 2010-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2010-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 */
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 * int entriesReturned = 0;
057 * int exceptionsCaught = 0;
058 *
059 * if (memberValues != null)
060 * {
061 * DNEntrySource entrySource =
062 * new DNEntrySource(connection, memberValues, "cn");
063 * try
064 * {
065 * while (true)
066 * {
067 * Entry memberEntry;
068 * try
069 * {
070 * memberEntry = entrySource.nextEntry();
071 * }
072 * catch (EntrySourceException ese)
073 * {
074 * // A problem was encountered while attempting to obtain an entry.
075 * // We may be able to continue reading entries (e.g., if the problem
076 * // was that the group referenced an entry that doesn't exist), or
077 * // we may not (e.g., if the problem was a significant search error
078 * // or problem with the connection).
079 * exceptionsCaught++;
080 * if (ese.mayContinueReading())
081 * {
082 * continue;
083 * }
084 * else
085 * {
086 * break;
087 * }
088 * }
089 *
090 * if (memberEntry == null)
091 * {
092 * // We've retrieved all of the entries for the given set of DNs.
093 * break;
094 * }
095 * else
096 * {
097 * entriesReturned++;
098 * }
099 * }
100 * }
101 * finally
102 * {
103 * entrySource.close();
104 * }
105 * }
106 * </PRE>
107 */
108 @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
109 public final class DNEntrySource
110 extends EntrySource
111 {
112 // The iterator to use to access the DNs. It will either be across DN or
113 // String objects.
114 private final Iterator<?> dnIterator;
115
116 // The connection to use to communicate with the directory server.
117 private final LDAPInterface connection;
118
119 // The set of attributes to include in entries that are returned.
120 private final String[] attributes;
121
122
123
124 /**
125 * Creates a new DN entry source with the provided information.
126 *
127 * @param connection The connection to the directory server from which the
128 * entries will be read. It must not be {@code null}.
129 * @param dns The set of DNs to be read. It must not be
130 * {@code null}.
131 * @param attributes The set of attributes to include in entries that are
132 * returned. If this is empty or {@code null}, then all
133 * user attributes will be requested.
134 */
135 public DNEntrySource(final LDAPInterface connection, final DN[] dns,
136 final String... attributes)
137 {
138 ensureNotNull(connection, dns);
139
140 this.connection = connection;
141 dnIterator = Arrays.asList(dns).iterator();
142
143 if (attributes == null)
144 {
145 this.attributes = NO_STRINGS;
146 }
147 else
148 {
149 this.attributes = attributes;
150 }
151 }
152
153
154
155 /**
156 * Creates a new DN entry source with the provided information.
157 *
158 * @param connection The connection to the directory server from which the
159 * entries will be read. It must not be {@code null}.
160 * @param dns The set of DNs to be read. It must not be
161 * {@code null}.
162 * @param attributes The set of attributes to include in entries that are
163 * returned. If this is empty or {@code null}, then all
164 * user attributes will be requested.
165 */
166 public DNEntrySource(final LDAPInterface connection, final String[] dns,
167 final String... attributes)
168 {
169 this(connection, Arrays.asList(dns), attributes);
170 }
171
172
173
174 /**
175 * Creates a new DN entry source with the provided information.
176 *
177 * @param connection The connection to the directory server from which the
178 * entries will be read. It must not be {@code null}.
179 * @param dns The set of DNs to be read. It must not be
180 * {@code null}.
181 * @param attributes The set of attributes to include in entries that are
182 * returned. If this is empty or {@code null}, then all
183 * user attributes will be requested.
184 */
185 public DNEntrySource(final LDAPInterface connection,
186 final Collection<String> dns, final String... attributes)
187 {
188 ensureNotNull(connection, dns);
189
190 this.connection = connection;
191 dnIterator = dns.iterator();
192
193 if (attributes == null)
194 {
195 this.attributes = NO_STRINGS;
196 }
197 else
198 {
199 this.attributes = attributes;
200 }
201 }
202
203
204
205 /**
206 * {@inheritDoc}
207 */
208 @Override()
209 public Entry nextEntry()
210 throws EntrySourceException
211 {
212 if (! dnIterator.hasNext())
213 {
214 return null;
215 }
216
217 final String dn = String.valueOf(dnIterator.next());
218 try
219 {
220 final Entry e = connection.getEntry(dn, attributes);
221 if (e == null)
222 {
223 throw new EntrySourceException(true,
224 ERR_DN_ENTRY_SOURCE_NO_SUCH_ENTRY.get(dn),
225 new LDAPException(ResultCode.NO_RESULTS_RETURNED));
226 }
227 else
228 {
229 return e;
230 }
231 }
232 catch (final LDAPException le)
233 {
234 debugException(le);
235 throw new EntrySourceException(true,
236 ERR_DN_ENTRY_SOURCE_ERR_RETRIEVING_ENTRY.get(dn,
237 getExceptionMessage(le)),
238 le);
239 }
240 }
241
242
243
244 /**
245 * {@inheritDoc}
246 */
247 @Override()
248 public void close()
249 {
250 // No implementation is required.
251 }
252 }