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 }