001/* 002 * Copyright 2010-2017 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2010-2017 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.ldap.sdk; 022 023 024 025import java.util.Arrays; 026import java.util.Collection; 027import java.util.Iterator; 028 029import com.unboundid.util.ThreadSafety; 030import com.unboundid.util.ThreadSafetyLevel; 031 032import static com.unboundid.ldap.sdk.LDAPMessages.*; 033import static com.unboundid.util.Debug.*; 034import static com.unboundid.util.StaticUtils.*; 035import 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) 109public 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}