001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2008 Sun Microsystems, Inc.
025 *      Portions Copyright 2013-2015 ForgeRock AS
026 */
027package org.opends.server.protocols.internal;
028
029import java.util.LinkedList;
030import java.util.List;
031import java.util.Set;
032
033import org.forgerock.opendj.ldap.DereferenceAliasesPolicy;
034import org.forgerock.opendj.ldap.SearchScope;
035import org.opends.server.api.ClientConnection;
036import org.opends.server.core.SearchOperationBasis;
037import org.opends.server.types.*;
038
039/**
040 * This class defines a subclass of the core search operation that is
041 * to be used for internal searches.  The primary difference between
042 * this class and the core search operation is that the search entries
043 * and references will be queued in memory rather than sent to a
044 * client since there is no real client.
045 */
046@org.opends.server.types.PublicAPI(
047     stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
048     mayInstantiate=true,
049     mayExtend=false,
050     mayInvoke=true)
051public final class InternalSearchOperation
052       extends SearchOperationBasis
053{
054  /** The internal search listener for this search, if one was provided. */
055  private InternalSearchListener searchListener;
056
057  /** The set of matching entries returned for this search. */
058  private LinkedList<SearchResultEntry> entryList;
059
060  /** The set of search references returned for this search. */
061  private List<SearchResultReference> referenceList;
062
063  /**
064   * Creates a new internal search operation with the provided information.
065   *
066   * @param internalConnection
067   *          The internal client connection with which this internal search
068   *          operation is associated.
069   * @param operationID
070   *          The operation ID for this internal search.
071   * @param messageID
072   *          The message ID for this internal search.
073   * @param request
074   *          The search request
075   */
076  public InternalSearchOperation(ClientConnection internalConnection, long operationID, int messageID,
077      SearchRequest request)
078  {
079    this(internalConnection, operationID, messageID, request, null);
080  }
081
082  /**
083   * Creates a new internal search operation with the provided information.
084   *
085   * @param  internalConnection  The internal client connection with
086   *                             which this internal search operation
087   *                             is associated.
088   * @param  operationID         The operation ID for this internal
089   *                             search.
090   * @param  messageID           The message ID for this internal
091   *                             search.
092   * @param  request             The search request
093   * @param  searchListener      The internal search listener that
094   *                             should be used to process the
095   *                             results, or <CODE>null</CODE> if
096   *                             they should be collected internally.
097   */
098  public InternalSearchOperation(ClientConnection internalConnection, long operationID, int messageID,
099      SearchRequest request, InternalSearchListener searchListener)
100  {
101    this(internalConnection, operationID, messageID,
102        request.getControls(),
103        request.getName(), request.getScope(),
104        request.getDereferenceAliasesPolicy(),
105        request.getSizeLimit(), request.getTimeLimit(), request.isTypesOnly(),
106        request.getFilter(), request.getAttributes(),
107        searchListener);
108  }
109
110  private InternalSearchOperation(
111              ClientConnection internalConnection,
112              long operationID, int messageID,
113              List<Control> requestControls, DN baseDN,
114              SearchScope scope, DereferenceAliasesPolicy derefPolicy,
115              int sizeLimit, int timeLimit, boolean typesOnly,
116              SearchFilter filter, Set<String> attributes,
117              InternalSearchListener searchListener)
118  {
119    super(internalConnection, operationID, messageID, requestControls,
120          baseDN, scope, derefPolicy, sizeLimit, timeLimit,
121          typesOnly, filter, attributes);
122
123
124
125
126    if (searchListener == null)
127    {
128      this.searchListener = null;
129      this.entryList      = new LinkedList<>();
130      this.referenceList  = new LinkedList<>();
131    }
132    else
133    {
134      this.searchListener = searchListener;
135      this.entryList      = null;
136      this.referenceList  = null;
137    }
138
139    setInternalOperation(true);
140  }
141
142  /**
143   * Retrieves the set of search result entries returned for this
144   * search.
145   *
146   * @return  The set of search result entries returned for this
147   *          search, or <CODE>null</CODE> if a custom internal search
148   *          listener is to be used.
149   */
150  public LinkedList<SearchResultEntry> getSearchEntries()
151  {
152    return entryList;
153  }
154
155
156
157  /**
158   * Provides the provided search result entry to the internal search
159   * listener if one was provided, or stores it in an internal list
160   * otherwise.
161   *
162   * @param  searchEntry  The search result entry returned for this
163   *                      search.
164   *
165   * @throws  DirectoryException  If a problem occurs while processing
166   *                              the provided entry and the search
167   *                              should be terminated.
168   */
169  @org.opends.server.types.PublicAPI(
170       stability=org.opends.server.types.StabilityLevel.PRIVATE,
171       mayInstantiate=false,
172       mayExtend=false,
173       mayInvoke=false)
174  public void addSearchEntry(SearchResultEntry searchEntry)
175         throws DirectoryException
176  {
177    if (searchListener == null)
178    {
179      entryList.add(searchEntry);
180    }
181    else
182    {
183      searchListener.handleInternalSearchEntry(this, searchEntry);
184    }
185  }
186
187
188
189  /**
190   * Retrieves the set of search result references returned for this
191   * search.
192   *
193   * @return  The set of search result references returned for this
194   *          search, or <CODE>null</CODE> if a custom internal search
195   *          listener is to be used.
196   */
197  public List<SearchResultReference> getSearchReferences()
198  {
199    return referenceList;
200  }
201
202
203
204  /**
205   * Provides the provided search result reference to the internal
206   * search listener if one was provided, or stores it in an internal
207   * list otherwise.
208   *
209   * @param  searchReference  The search result reference returned for
210   *                          this search.
211   *
212   * @throws  DirectoryException  If a problem occurs while processing
213   *                              the provided reference and the
214   *                              search should be terminated.
215   */
216  @org.opends.server.types.PublicAPI(
217       stability=org.opends.server.types.StabilityLevel.PRIVATE,
218       mayInstantiate=false,
219       mayExtend=false,
220       mayInvoke=false)
221  public void addSearchReference(
222                   SearchResultReference searchReference)
223         throws DirectoryException
224  {
225    if (searchListener == null)
226    {
227      referenceList.add(searchReference);
228    }
229    else
230    {
231      searchListener.handleInternalSearchReference(this,
232                                                   searchReference);
233    }
234  }
235
236
237
238  /**
239   * Sends the provided search result entry to the client.
240   *
241   * @param  searchEntry  The search result entry to be sent to the
242   *                      client.
243   *
244   * @throws  DirectoryException  If a problem occurs while attempting
245   *                              to send the entry to the client and
246   *                              the search should be terminated.
247   */
248  @org.opends.server.types.PublicAPI(
249       stability=org.opends.server.types.StabilityLevel.PRIVATE,
250       mayInstantiate=false,
251       mayExtend=false,
252       mayInvoke=false)
253  @Override
254  public void sendSearchEntry(SearchResultEntry searchEntry)
255         throws DirectoryException
256  {
257    addSearchEntry(searchEntry);
258  }
259
260
261
262  /**
263   * Sends the provided search result reference to the client.
264   *
265   * @param  searchReference  The search result reference to be sent
266   *                          to the client.
267   *
268   * @return  {@code true} if the client is able to accept referrals,
269   *          or {@code false} if the client cannot handle referrals
270   *          and no more attempts should be made to send them for the
271   *          associated search operation.
272   *
273   * @throws  DirectoryException  If a problem occurs while attempting
274   *                              to send the reference to the client
275   *                              and the search should be terminated.
276   */
277  @org.opends.server.types.PublicAPI(
278       stability=org.opends.server.types.StabilityLevel.PRIVATE,
279       mayInstantiate=false,
280       mayExtend=false,
281       mayInvoke=false)
282  @Override
283  public boolean sendSearchReference(
284                      SearchResultReference searchReference)
285         throws DirectoryException
286  {
287    addSearchReference(searchReference);
288    return true;
289  }
290}
291