001/* 002 * Copyright 2009-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2020 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-2020 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.StaticUtils; 050import com.unboundid.util.ThreadSafety; 051import com.unboundid.util.ThreadSafetyLevel; 052 053import static com.unboundid.ldap.sdk.persist.PersistMessages.*; 054 055 056 057/** 058 * This class provides a mechanism for iterating through the objects returned 059 * by a search operation performed using one of the {@code search} methods in 060 * the {@link LDAPPersister} class. However, it has a couple of notable 061 * differences from a standard Java {@code Iterator} object: 062 * <UL> 063 * <LI>It does not have a {@code hasNext} method. Instead, the {@link #next} 064 * method will return {@code null} when there are no more objects in the 065 * set of results.</LI> 066 * <LI>The {@link #next} method may throw an exception if a problem occurs 067 * while trying to read an entry or decode it as an object of the 068 * appropriate type. This does not necessarily mean that the search is 069 * complete, and the {@link #next} method should be called again to see 070 * if there are any more objects to retrieve.</LI> 071 * <LI>If you wish to stop iterating through the results before all of them 072 * have been retrieved, then you must call the {@link #close} method 073 * </UL> 074 * 075 * @param <T> The type of object handled by this class. 076 */ 077@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 078public final class PersistedObjects<T> 079 implements Serializable, Closeable 080{ 081 /** 082 * The serial version UID for this serializable class. 083 */ 084 private static final long serialVersionUID = 7430494946944736169L; 085 086 087 088 // The LDAP entry source that will be used to read matching entries. 089 private final EntrySource entrySource; 090 091 // The LDAP persister that will be used to decode the entries that are 092 // returned. 093 private final LDAPPersister<T> persister; 094 095 096 097 /** 098 * Creates a new {@code PersistedObjects} object that will read entries from 099 * the provided entry source. 100 * 101 * @param persister The persister that will be used to decode entries that 102 * are returned. 103 * @param entrySource The entry source that will be used to read entries 104 * returned from the search. 105 */ 106 PersistedObjects(final LDAPPersister<T> persister, 107 final EntrySource entrySource) 108 { 109 this.persister = persister; 110 this.entrySource = entrySource; 111 } 112 113 114 115 /** 116 * Retrieves the next object returned from the search request. This method 117 * may block until the necessary information has been received from the 118 * server. 119 * 120 * @return The next object returned from the search request, or {@code null} 121 * if all objects have been read. 122 * 123 * @throws LDAPPersistException If a problem occurs while reading the next 124 * entry from the server, or when trying to 125 * decode that entry as an object. 126 */ 127 public T next() 128 throws LDAPPersistException 129 { 130 final Entry entry; 131 try 132 { 133 entry = entrySource.nextEntry(); 134 } 135 catch (final Exception e) 136 { 137 Debug.debugException(e); 138 139 final Throwable cause = e.getCause(); 140 if ((cause != null) && (cause instanceof LDAPException)) 141 { 142 throw new LDAPPersistException((LDAPException) cause); 143 } 144 else 145 { 146 throw new LDAPPersistException( 147 ERR_OBJECT_SEARCH_RESULTS_ENTRY_SOURCE_EXCEPTION.get( 148 StaticUtils.getExceptionMessage(e)), 149 e); 150 } 151 } 152 153 if (entry == null) 154 { 155 return null; 156 } 157 else 158 { 159 return persister.decode(entry); 160 } 161 } 162 163 164 165 /** 166 * Indicates that you wish to stop iterating through search results and will 167 * not be retrieving any additional objects. This method MUST be called to 168 * avoid leaking resources if you stop iterating through results before the 169 * {@link #next} method returns {@code null} to indicate that there are no 170 * more objects to retrieve. This method MAY be called after the search has 171 * completed (including being called multiple times) with no adverse effects. 172 */ 173 @Override() 174 public void close() 175 { 176 entrySource.close(); 177 } 178 179 180 181 /** 182 * Retrieves the search result for the search operation, if available. It 183 * will not be available until the search has completed (as indicated by a 184 * {@code null} return value from the {@link #next} method), and for some use 185 * cases it may never be available. 186 * 187 * @return The search result for the search operation, or {@code null} if it 188 * is not available (e.g., because the search has not yet completed). 189 */ 190 public SearchResult getSearchResult() 191 { 192 if (entrySource instanceof LDAPEntrySource) 193 { 194 return ((LDAPEntrySource) entrySource).getSearchResult(); 195 } 196 else 197 { 198 return null; 199 } 200 } 201}