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   *     http://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      /** Speedup for logs */
58      private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
59  
60      /** a reference to hold the retrieved SearchResponse object from SearchFuture */
61      private Response response;
62  
63      /** The encapsulated search cursor */
64      private SearchCursor searchCursor;
65  
66      /** The underlying messageId */
67      private int messageId;
68  
69  
70      /**
71       * Instantiates a new search cursor, embedding a SearchCursor.
72       *
73       * @param searchCursor the embedded SearchResponse cursor
74       */
75      public EntryCursorImpl( SearchCursor searchCursor )
76      {
77          if ( IS_DEBUG )
78          {
79              LOG_CURSOR.debug( "Creating EntryCursorImpl {}", this );
80          }
81  
82          this.searchCursor = searchCursor;
83          messageId = -1;
84      }
85  
86  
87      /**
88       * {@inheritDoc}
89       */
90      @Override
91      public boolean next() throws LdapException, CursorException
92      {
93          if ( !searchCursor.next() )
94          {
95              return false;
96          }
97  
98          try
99          {
100             do
101             {
102                 response = searchCursor.get();
103 
104                 if ( response == null )
105                 {
106                     throw new LdapException( LdapNetworkConnection.TIME_OUT_ERROR );
107                 }
108 
109                 messageId = response.getMessageId();
110 
111                 if ( response instanceof SearchResultEntry )
112                 {
113                     return true;
114                 }
115 
116                 if ( response instanceof SearchResultReference )
117                 {
118                     return true;
119                 }
120             }
121             while ( !( response instanceof SearchResultDone ) );
122 
123             return false;
124         }
125         catch ( Exception e )
126         {
127             LdapException ldapException = new LdapException( LdapNetworkConnection.NO_RESPONSE_ERROR );
128             ldapException.initCause( e );
129 
130             // close the cursor
131             try
132             {
133                 close( ldapException );
134             }
135             catch ( IOException ioe )
136             {
137                 throw new LdapException( ioe.getMessage(), ioe );
138             }
139 
140             throw ldapException;
141         }
142     }
143 
144 
145     /**
146      * {@inheritDoc}
147      */
148     @Override
149     public Entry get() throws CursorException
150     {
151         if ( !searchCursor.available() )
152         {
153             throw new InvalidCursorPositionException();
154         }
155 
156         try
157         {
158             do
159             {
160                 if ( response instanceof SearchResultEntry )
161                 {
162                     return ( ( SearchResultEntry ) response ).getEntry();
163                 }
164 
165                 if ( response instanceof SearchResultReference )
166                 {
167                     throw new LdapReferralException( ( ( SearchResultReference ) response ).getReferral().getLdapUrls() );
168                 }
169             }
170             while ( next() && !( response instanceof SearchResultDone ) );
171         }
172         catch ( LdapReferralException lre )
173         {
174             throw new CursorLdapReferralException( lre );
175         }
176         catch ( Exception e )
177         {
178             throw new CursorException( e );
179         }
180 
181         return null;
182     }
183 
184 
185     /**
186      * {@inheritDoc}
187      */
188     @Override
189     public SearchResultDone getSearchResultDone()
190     {
191         return searchCursor.getSearchResultDone();
192     }
193 
194 
195     /**
196      * {@inheritDoc}
197      */
198     @Override
199     public boolean available()
200     {
201         return searchCursor.available();
202     }
203 
204 
205     /**
206      * {@inheritDoc}
207      */
208     @Override
209     public void close() throws IOException
210     {
211         if ( IS_DEBUG )
212         {
213             LOG_CURSOR.debug( "Closing EntryCursorImpl {}", this );
214         }
215 
216         searchCursor.close();
217     }
218 
219 
220     /**
221      * {@inheritDoc}
222      */
223     @Override
224     public void close( Exception cause ) throws IOException
225     {
226         if ( IS_DEBUG )
227         {
228             LOG_CURSOR.debug( "Closing EntryCursorImpl {}", this );
229         }
230 
231         searchCursor.close( cause );
232     }
233 
234 
235     // rest of all operations will throw UnsupportedOperationException
236 
237     /**
238      * This operation is not supported in SearchCursor.
239      * {@inheritDoc}
240      */
241     @Override
242     public void after( Entry element ) throws LdapException, CursorException
243     {
244         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
245             .concat( "." ).concat( "after( Response element )" ) ) );
246     }
247 
248 
249     /**
250      * This operation is not supported in SearchCursor.
251      * {@inheritDoc}
252      */
253     @Override
254     public void afterLast() throws LdapException, CursorException
255     {
256         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
257             .concat( "." ).concat( "afterLast()" ) ) );
258     }
259 
260 
261     /**
262      * This operation is not supported in SearchCursor.
263      * {@inheritDoc}
264      */
265     @Override
266     public void before( Entry element ) throws LdapException, CursorException
267     {
268         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
269             .concat( "." ).concat( "before( Response element )" ) ) );
270     }
271 
272 
273     /**
274      * This operation is not supported in SearchCursor.
275      * {@inheritDoc}
276      */
277     @Override
278     public void beforeFirst() throws LdapException, CursorException
279     {
280         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
281             .concat( "." ).concat( "beforeFirst()" ) ) );
282     }
283 
284 
285     /**
286      * This operation is not supported in SearchCursor.
287      * {@inheritDoc}
288      */
289     @Override
290     public boolean first() throws LdapException, CursorException
291     {
292         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
293             .concat( "." ).concat( "first()" ) ) );
294     }
295 
296 
297     /**
298      * This operation is not supported in SearchCursor.
299      * {@inheritDoc}
300      */
301     @Override
302     public boolean last() throws LdapException, CursorException
303     {
304         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
305             .concat( "." ).concat( "last()" ) ) );
306     }
307 
308 
309     /**
310      * This operation is not supported in SearchCursor.
311      * {@inheritDoc}
312      */
313     @Override
314     public boolean previous() throws LdapException, CursorException
315     {
316         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
317             .concat( "." ).concat( "previous()" ) ) );
318     }
319 
320 
321     /**
322      * {@inheritDoc}
323      */
324     @Override
325     public int getMessageId()
326     {
327         return messageId;
328     }
329 }