View Javadoc
1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     https://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  
21  package org.apache.directory.ldap.client.api;
22  
23  
24  import java.io.IOException;
25  
26  import org.apache.directory.api.i18n.I18n;
27  import org.apache.directory.api.ldap.model.constants.Loggers;
28  import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
29  import org.apache.directory.api.ldap.model.cursor.CursorException;
30  import org.apache.directory.api.ldap.model.cursor.CursorLdapReferralException;
31  import org.apache.directory.api.ldap.model.cursor.EntryCursor;
32  import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
33  import org.apache.directory.api.ldap.model.cursor.SearchCursor;
34  import org.apache.directory.api.ldap.model.entry.Entry;
35  import org.apache.directory.api.ldap.model.exception.LdapException;
36  import org.apache.directory.api.ldap.model.exception.LdapReferralException;
37  import org.apache.directory.api.ldap.model.message.Response;
38  import org.apache.directory.api.ldap.model.message.SearchResultDone;
39  import org.apache.directory.api.ldap.model.message.SearchResultEntry;
40  import org.apache.directory.api.ldap.model.message.SearchResultReference;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  
44  
45  /**
46   * An implementation of Cursor based on the underlying SearchFuture instance.
47   * 
48   * Note: This is a forward only cursor hence the only valid operations are next(), get() and close() 
49   * 
50   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
51   */
52  public class EntryCursorImpl extends AbstractCursor<Entry> implements EntryCursor
53  {
54      /** A dedicated log for cursors */
55      private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
56  
57      /** a reference to hold the retrieved SearchResponse object from SearchFuture */
58      private Response response;
59  
60      /** The encapsulated search cursor */
61      private SearchCursor searchCursor;
62  
63      /** The underlying messageId */
64      private int messageId;
65  
66  
67      /**
68       * Instantiates a new search cursor, embedding a SearchCursor.
69       *
70       * @param searchCursor the embedded SearchResponse cursor
71       */
72      public EntryCursorImpl( SearchCursor searchCursor )
73      {
74          if ( LOG_CURSOR.isDebugEnabled() )
75          {
76              LOG_CURSOR.debug( I18n.msg( I18n.MSG_04161_CREATING_ENTRY_CURSOR, this ) );
77          }
78  
79          this.searchCursor = searchCursor;
80          messageId = -1;
81      }
82  
83  
84      /**
85       * {@inheritDoc}
86       */
87      @Override
88      public boolean next() throws LdapException, CursorException
89      {
90          if ( !searchCursor.next() )
91          {
92              return false;
93          }
94  
95          try
96          {
97              do
98              {
99                  response = searchCursor.get();
100 
101                 if ( response == null )
102                 {
103                     throw new LdapException( LdapNetworkConnection.TIME_OUT_ERROR );
104                 }
105 
106                 messageId = response.getMessageId();
107 
108                 if ( response instanceof SearchResultEntry )
109                 {
110                     return true;
111                 }
112 
113                 if ( response instanceof SearchResultReference )
114                 {
115                     return true;
116                 }
117             }
118             while ( !( response instanceof SearchResultDone ) );
119 
120             return false;
121         }
122         catch ( Exception e )
123         {
124             LdapException ldapException = new LdapException( LdapNetworkConnection.NO_RESPONSE_ERROR );
125             ldapException.initCause( e );
126 
127             // close the cursor
128             try
129             {
130                 close( ldapException );
131             }
132             catch ( IOException ioe )
133             {
134                 throw new LdapException( ioe.getMessage(), ioe );
135             }
136 
137             throw ldapException;
138         }
139     }
140 
141 
142     /**
143      * {@inheritDoc}
144      */
145     @Override
146     public Entry get() throws CursorException
147     {
148         if ( !searchCursor.available() )
149         {
150             throw new InvalidCursorPositionException();
151         }
152 
153         try
154         {
155             do
156             {
157                 if ( response instanceof SearchResultEntry )
158                 {
159                     return ( ( SearchResultEntry ) response ).getEntry();
160                 }
161 
162                 if ( response instanceof SearchResultReference )
163                 {
164                     throw new LdapReferralException( ( ( SearchResultReference ) response ).getReferral().getLdapUrls() );
165                 }
166             }
167             while ( next() && !( response instanceof SearchResultDone ) );
168         }
169         catch ( LdapReferralException lre )
170         {
171             throw new CursorLdapReferralException( lre );
172         }
173         catch ( Exception e )
174         {
175             throw new CursorException( e );
176         }
177 
178         return null;
179     }
180 
181 
182     /**
183      * {@inheritDoc}
184      */
185     @Override
186     public SearchResultDone getSearchResultDone()
187     {
188         return searchCursor.getSearchResultDone();
189     }
190 
191 
192     /**
193      * {@inheritDoc}
194      */
195     @Override
196     public boolean available()
197     {
198         return searchCursor.available();
199     }
200 
201 
202     /**
203      * {@inheritDoc}
204      */
205     @Override
206     public void close() throws IOException
207     {
208         if ( LOG_CURSOR.isDebugEnabled() )
209         {
210             LOG_CURSOR.debug( I18n.msg( I18n.MSG_04162_CLOSING_ENTRY_CURSOR, this ) );
211         }
212 
213         searchCursor.close();
214     }
215 
216 
217     /**
218      * {@inheritDoc}
219      */
220     @Override
221     public void close( Exception cause ) throws IOException
222     {
223         if ( LOG_CURSOR.isDebugEnabled() )
224         {
225             LOG_CURSOR.debug( I18n.msg( I18n.MSG_04162_CLOSING_ENTRY_CURSOR, this ) );
226         }
227 
228         searchCursor.close( cause );
229     }
230 
231 
232     // rest of all operations will throw UnsupportedOperationException
233 
234     /**
235      * This operation is not supported in SearchCursor.
236      * {@inheritDoc}
237      */
238     @Override
239     public void after( Entry element ) throws LdapException, CursorException
240     {
241         throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
242             .concat( "." ).concat( "after( Response element )" ) ) );
243     }
244 
245 
246     /**
247      * This operation is not supported in SearchCursor.
248      * {@inheritDoc}
249      */
250     @Override
251     public void afterLast() throws LdapException, CursorException
252     {
253         throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
254             .concat( "." ).concat( "afterLast()" ) ) );
255     }
256 
257 
258     /**
259      * This operation is not supported in SearchCursor.
260      * {@inheritDoc}
261      */
262     @Override
263     public void before( Entry element ) throws LdapException, CursorException
264     {
265         throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
266             .concat( "." ).concat( "before( Response element )" ) ) );
267     }
268 
269 
270     /**
271      * This operation is not supported in SearchCursor.
272      * {@inheritDoc}
273      */
274     @Override
275     public void beforeFirst() throws LdapException, CursorException
276     {
277         throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
278             .concat( "." ).concat( "beforeFirst()" ) ) );
279     }
280 
281 
282     /**
283      * This operation is not supported in SearchCursor.
284      * {@inheritDoc}
285      */
286     @Override
287     public boolean first() throws LdapException, CursorException
288     {
289         throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
290             .concat( "." ).concat( "first()" ) ) );
291     }
292 
293 
294     /**
295      * This operation is not supported in SearchCursor.
296      * {@inheritDoc}
297      */
298     @Override
299     public boolean last() throws LdapException, CursorException
300     {
301         throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
302             .concat( "." ).concat( "last()" ) ) );
303     }
304 
305 
306     /**
307      * This operation is not supported in SearchCursor.
308      * {@inheritDoc}
309      */
310     @Override
311     public boolean previous() throws LdapException, CursorException
312     {
313         throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
314             .concat( "." ).concat( "previous()" ) ) );
315     }
316 
317 
318     /**
319      * {@inheritDoc}
320      */
321     @Override
322     public int getMessageId()
323     {
324         return messageId;
325     }
326 }