001/* 002 * Copyright 2009-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2009-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.persist; 037 038 039 040import java.io.Closeable; 041import java.io.Serializable; 042 043import com.unboundid.ldap.sdk.Entry; 044import com.unboundid.ldap.sdk.EntrySource; 045import com.unboundid.ldap.sdk.LDAPEntrySource; 046import com.unboundid.ldap.sdk.LDAPException; 047import com.unboundid.ldap.sdk.SearchResult; 048import com.unboundid.util.Debug; 049import com.unboundid.util.NotNull; 050import com.unboundid.util.Nullable; 051import com.unboundid.util.StaticUtils; 052import com.unboundid.util.ThreadSafety; 053import com.unboundid.util.ThreadSafetyLevel; 054 055import static com.unboundid.ldap.sdk.persist.PersistMessages.*; 056 057 058 059/** 060 * This class provides a mechanism for iterating through the objects returned 061 * by a search operation performed using one of the {@code search} methods in 062 * the {@link LDAPPersister} class. However, it has a couple of notable 063 * differences from a standard Java {@code Iterator} object: 064 * <UL> 065 * <LI>It does not have a {@code hasNext} method. Instead, the {@link #next} 066 * method will return {@code null} when there are no more objects in the 067 * set of results.</LI> 068 * <LI>The {@link #next} method may throw an exception if a problem occurs 069 * while trying to read an entry or decode it as an object of the 070 * appropriate type. This does not necessarily mean that the search is 071 * complete, and the {@link #next} method should be called again to see 072 * if there are any more objects to retrieve.</LI> 073 * <LI>If you wish to stop iterating through the results before all of them 074 * have been retrieved, then you must call the {@link #close} method 075 * </UL> 076 * 077 * @param <T> The type of object handled by this class. 078 */ 079@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 080public final class PersistedObjects<T> 081 implements Serializable, Closeable 082{ 083 /** 084 * The serial version UID for this serializable class. 085 */ 086 private static final long serialVersionUID = 7430494946944736169L; 087 088 089 090 // The LDAP entry source that will be used to read matching entries. 091 @NotNull private final EntrySource entrySource; 092 093 // The LDAP persister that will be used to decode the entries that are 094 // returned. 095 @NotNull private final LDAPPersister<T> persister; 096 097 098 099 /** 100 * Creates a new {@code PersistedObjects} object that will read entries from 101 * the provided entry source. 102 * 103 * @param persister The persister that will be used to decode entries that 104 * are returned. 105 * @param entrySource The entry source that will be used to read entries 106 * returned from the search. 107 */ 108 PersistedObjects(@NotNull final LDAPPersister<T> persister, 109 @NotNull final EntrySource entrySource) 110 { 111 this.persister = persister; 112 this.entrySource = entrySource; 113 } 114 115 116 117 /** 118 * Retrieves the next object returned from the search request. This method 119 * may block until the necessary information has been received from the 120 * server. 121 * 122 * @return The next object returned from the search request, or {@code null} 123 * if all objects have been read. 124 * 125 * @throws LDAPPersistException If a problem occurs while reading the next 126 * entry from the server, or when trying to 127 * decode that entry as an object. 128 */ 129 @Nullable() 130 public T next() 131 throws LDAPPersistException 132 { 133 final Entry entry; 134 try 135 { 136 entry = entrySource.nextEntry(); 137 } 138 catch (final Exception e) 139 { 140 Debug.debugException(e); 141 142 final Throwable cause = e.getCause(); 143 if ((cause != null) && (cause instanceof LDAPException)) 144 { 145 throw new LDAPPersistException((LDAPException) cause); 146 } 147 else 148 { 149 throw new LDAPPersistException( 150 ERR_OBJECT_SEARCH_RESULTS_ENTRY_SOURCE_EXCEPTION.get( 151 StaticUtils.getExceptionMessage(e)), 152 e); 153 } 154 } 155 156 if (entry == null) 157 { 158 return null; 159 } 160 else 161 { 162 return persister.decode(entry); 163 } 164 } 165 166 167 168 /** 169 * Indicates that you wish to stop iterating through search results and will 170 * not be retrieving any additional objects. This method MUST be called to 171 * avoid leaking resources if you stop iterating through results before the 172 * {@link #next} method returns {@code null} to indicate that there are no 173 * more objects to retrieve. This method MAY be called after the search has 174 * completed (including being called multiple times) with no adverse effects. 175 */ 176 @Override() 177 public void close() 178 { 179 entrySource.close(); 180 } 181 182 183 184 /** 185 * Retrieves the search result for the search operation, if available. It 186 * will not be available until the search has completed (as indicated by a 187 * {@code null} return value from the {@link #next} method), and for some use 188 * cases it may never be available. 189 * 190 * @return The search result for the search operation, or {@code null} if it 191 * is not available (e.g., because the search has not yet completed). 192 */ 193 @Nullable() 194 public SearchResult getSearchResult() 195 { 196 if (entrySource instanceof LDAPEntrySource) 197 { 198 return ((LDAPEntrySource) entrySource).getSearchResult(); 199 } 200 else 201 { 202 return null; 203 } 204 } 205}