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 org.apache.directory.api.i18n.I18n;
25  import org.apache.directory.api.ldap.model.constants.Loggers;
26  import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
27  import org.apache.directory.api.ldap.model.cursor.CursorException;
28  import org.apache.directory.api.ldap.model.cursor.CursorLdapReferralException;
29  import org.apache.directory.api.ldap.model.cursor.EntryCursor;
30  import org.apache.directory.api.ldap.model.cursor.InvalidCursorPositionException;
31  import org.apache.directory.api.ldap.model.cursor.SearchCursor;
32  import org.apache.directory.api.ldap.model.entry.Entry;
33  import org.apache.directory.api.ldap.model.exception.LdapException;
34  import org.apache.directory.api.ldap.model.exception.LdapReferralException;
35  import org.apache.directory.api.ldap.model.message.Response;
36  import org.apache.directory.api.ldap.model.message.SearchResultDone;
37  import org.apache.directory.api.ldap.model.message.SearchResultEntry;
38  import org.apache.directory.api.ldap.model.message.SearchResultReference;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  
43  /**
44   * An implementation of Cursor based on the underlying SearchFuture instance.
45   * 
46   * Note: This is a forward only cursor hence the only valid operations are next(), get() and close() 
47   * 
48   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
49   */
50  public class EntryCursorImpl extends AbstractCursor<Entry> implements EntryCursor
51  {
52      /** A dedicated log for cursors */
53      private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
54  
55      /** Speedup for logs */
56      private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
57  
58      /** a reference to hold the retrieved SearchResponse object from SearchFuture */
59      private Response response;
60  
61      /** The encapsulated search cursor */
62      private SearchCursor searchCursor;
63  
64      /** The underlying messageId */
65      private int messageId;
66  
67  
68      /**
69       * Instantiates a new search cursor, embedding a SearchCursor.
70       *
71       * @param searchCursor the embedded SearchResponse cursor
72       */
73      public EntryCursorImpl( SearchCursor searchCursor )
74      {
75          if ( IS_DEBUG )
76          {
77              LOG_CURSOR.debug( "Creating EntryCursorImpl {}", this );
78          }
79  
80          this.searchCursor = searchCursor;
81          messageId = -1;
82      }
83  
84  
85      /**
86       * {@inheritDoc}
87       */
88      public boolean next() throws LdapException, CursorException
89      {
90          if ( !searchCursor.next() )
91          {
92              return false;
93          }
94  
95          try
96          {
97  
98              do
99              {
100                 response = searchCursor.get();
101 
102                 if ( response == null )
103                 {
104                     throw new LdapException( LdapNetworkConnection.TIME_OUT_ERROR );
105                 }
106 
107                 messageId = response.getMessageId();
108 
109                 if ( response instanceof SearchResultEntry )
110                 {
111                     return true;
112                 }
113 
114                 if ( response instanceof SearchResultReference )
115                 {
116                     return true;
117                 }
118             }
119             while ( !( response instanceof SearchResultDone ) );
120 
121             return false;
122         }
123         catch ( Exception e )
124         {
125             LdapException ldapException = new LdapException( LdapNetworkConnection.NO_RESPONSE_ERROR );
126             ldapException.initCause( e );
127 
128             // close the cursor
129             close( ldapException );
130 
131             throw ldapException;
132         }
133     }
134 
135 
136     /**
137      * {@inheritDoc}
138      */
139     public Entry get() throws CursorException
140     {
141         if ( !searchCursor.available() )
142         {
143             throw new InvalidCursorPositionException();
144         }
145 
146         try
147         {
148             do
149             {
150                 if ( response instanceof SearchResultEntry )
151                 {
152                     return ( ( SearchResultEntry ) response ).getEntry();
153                 }
154 
155                 if ( response instanceof SearchResultReference )
156                 {
157                     throw new LdapReferralException( ( ( SearchResultReference ) response ).getReferral().getLdapUrls() );
158                 }
159             }
160             while ( next() && !( response instanceof SearchResultDone ) );
161         }
162         catch ( LdapReferralException lre )
163         {
164             throw new CursorLdapReferralException( lre );
165         }
166         catch ( Exception e )
167         {
168             throw new CursorException( e );
169         }
170 
171         return null;
172     }
173 
174 
175     /**
176      * {@inheritDoc}
177      */
178     public SearchResultDone getSearchResultDone()
179     {
180         return searchCursor.getSearchResultDone();
181     }
182 
183 
184     /**
185      * {@inheritDoc}
186      */
187     public boolean available()
188     {
189         return searchCursor.available();
190     }
191 
192 
193     /**
194      * {@inheritDoc}
195      */
196     @Override
197     public void close()
198     {
199         if ( IS_DEBUG )
200         {
201             LOG_CURSOR.debug( "Closing EntryCursorImpl {}", this );
202         }
203 
204         searchCursor.close();
205     }
206 
207 
208     /**
209      * {@inheritDoc}
210      */
211     @Override
212     public void close( Exception cause )
213     {
214         if ( IS_DEBUG )
215         {
216             LOG_CURSOR.debug( "Closing EntryCursorImpl {}", this );
217         }
218 
219         searchCursor.close( cause );
220     }
221 
222 
223     // rest of all operations will throw UnsupportedOperationException
224 
225     /**
226      * This operation is not supported in SearchCursor.
227      * {@inheritDoc}
228      */
229     public void after( Entry element ) throws LdapException, CursorException
230     {
231         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
232             .concat( "." ).concat( "after( Response element )" ) ) );
233     }
234 
235 
236     /**
237      * This operation is not supported in SearchCursor.
238      * {@inheritDoc}
239      */
240     public void afterLast() throws LdapException, CursorException
241     {
242         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
243             .concat( "." ).concat( "afterLast()" ) ) );
244     }
245 
246 
247     /**
248      * This operation is not supported in SearchCursor.
249      * {@inheritDoc}
250      */
251     public void before( Entry element ) throws LdapException, CursorException
252     {
253         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
254             .concat( "." ).concat( "before( Response element )" ) ) );
255     }
256 
257 
258     /**
259      * This operation is not supported in SearchCursor.
260      * {@inheritDoc}
261      */
262     public void beforeFirst() throws LdapException, CursorException
263     {
264         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
265             .concat( "." ).concat( "beforeFirst()" ) ) );
266     }
267 
268 
269     /**
270      * This operation is not supported in SearchCursor.
271      * {@inheritDoc}
272      */
273     public boolean first() throws LdapException, CursorException
274     {
275         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
276             .concat( "." ).concat( "first()" ) ) );
277     }
278 
279 
280     /**
281      * This operation is not supported in SearchCursor.
282      * {@inheritDoc}
283      */
284     public boolean last() throws LdapException, CursorException
285     {
286         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
287             .concat( "." ).concat( "last()" ) ) );
288     }
289 
290 
291     /**
292      * This operation is not supported in SearchCursor.
293      * {@inheritDoc}
294      */
295     public boolean previous() throws LdapException, CursorException
296     {
297         throw new UnsupportedOperationException( I18n.err( I18n.ERR_02014_UNSUPPORTED_OPERATION, getClass().getName()
298             .concat( "." ).concat( "previous()" ) ) );
299     }
300 
301 
302     /**
303      * {@inheritDoc}
304      */
305     public int getMessageId()
306     {
307         return messageId;
308     }
309 }