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