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.api.dsmlv2.engine;
22  
23  
24  import java.io.BufferedWriter;
25  import java.io.ByteArrayOutputStream;
26  import java.io.File;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.io.OutputStream;
30  import java.io.OutputStreamWriter;
31  import java.nio.charset.StandardCharsets;
32  
33  import org.apache.commons.codec.Charsets;
34  import org.apache.directory.api.dsmlv2.DsmlDecorator;
35  import org.apache.directory.api.dsmlv2.Dsmlv2Parser;
36  import org.apache.directory.api.dsmlv2.ParserUtils;
37  import org.apache.directory.api.dsmlv2.request.BatchRequestDsml;
38  import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.OnError;
39  import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.Processing;
40  import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.ResponseOrder;
41  import org.apache.directory.api.dsmlv2.request.Dsmlv2Grammar;
42  import org.apache.directory.api.dsmlv2.response.AddResponseDsml;
43  import org.apache.directory.api.dsmlv2.response.BatchResponseDsml;
44  import org.apache.directory.api.dsmlv2.response.BindResponseDsml;
45  import org.apache.directory.api.dsmlv2.response.CompareResponseDsml;
46  import org.apache.directory.api.dsmlv2.response.DelResponseDsml;
47  import org.apache.directory.api.dsmlv2.response.ErrorResponse;
48  import org.apache.directory.api.dsmlv2.response.ErrorResponse.ErrorResponseType;
49  import org.apache.directory.api.dsmlv2.response.ExtendedResponseDsml;
50  import org.apache.directory.api.dsmlv2.response.ModDNResponseDsml;
51  import org.apache.directory.api.dsmlv2.response.ModifyResponseDsml;
52  import org.apache.directory.api.dsmlv2.response.SearchResponseDsml;
53  import org.apache.directory.api.dsmlv2.response.SearchResultDoneDsml;
54  import org.apache.directory.api.dsmlv2.response.SearchResultEntryDsml;
55  import org.apache.directory.api.dsmlv2.response.SearchResultReferenceDsml;
56  import org.apache.directory.api.i18n.I18n;
57  import org.apache.directory.api.ldap.model.cursor.SearchCursor;
58  import org.apache.directory.api.ldap.model.exception.LdapException;
59  import org.apache.directory.api.ldap.model.message.AbandonRequest;
60  import org.apache.directory.api.ldap.model.message.AddRequest;
61  import org.apache.directory.api.ldap.model.message.AddResponse;
62  import org.apache.directory.api.ldap.model.message.BindRequest;
63  import org.apache.directory.api.ldap.model.message.BindRequestImpl;
64  import org.apache.directory.api.ldap.model.message.BindResponse;
65  import org.apache.directory.api.ldap.model.message.CompareRequest;
66  import org.apache.directory.api.ldap.model.message.CompareResponse;
67  import org.apache.directory.api.ldap.model.message.DeleteRequest;
68  import org.apache.directory.api.ldap.model.message.DeleteResponse;
69  import org.apache.directory.api.ldap.model.message.ExtendedRequest;
70  import org.apache.directory.api.ldap.model.message.ExtendedResponse;
71  import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
72  import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
73  import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
74  import org.apache.directory.api.ldap.model.message.ModifyRequest;
75  import org.apache.directory.api.ldap.model.message.ModifyResponse;
76  import org.apache.directory.api.ldap.model.message.Request;
77  import org.apache.directory.api.ldap.model.message.Response;
78  import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
79  import org.apache.directory.api.ldap.model.message.SearchRequest;
80  import org.apache.directory.api.ldap.model.message.SearchResultDone;
81  import org.apache.directory.api.ldap.model.message.SearchResultEntry;
82  import org.apache.directory.api.ldap.model.message.SearchResultReference;
83  import org.apache.directory.api.util.Strings;
84  import org.apache.directory.ldap.client.api.LdapConnection;
85  import org.apache.directory.ldap.client.api.LdapNetworkConnection;
86  import org.dom4j.Element;
87  import org.dom4j.Namespace;
88  import org.slf4j.Logger;
89  import org.slf4j.LoggerFactory;
90  import org.xmlpull.v1.XmlPullParserException;
91  
92  
93  /**
94   * This is the DSMLv2Engine. It can be use to execute operations on a LDAP Server and get the results of these operations.
95   * The format used for request and responses is the DSMLv2 format.
96   *
97   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
98   */
99  public class Dsmlv2Engine
100 {
101     /** The user. */
102     protected String user;
103 
104     /** The password. */
105     protected String password;
106 
107     /** The LDAP connection */
108     protected LdapConnection connection;
109 
110     /** The DSVMv2 parser. */
111     protected Dsmlv2Parser parser;
112 
113     /** The continue on error flag. */
114     protected boolean continueOnError;
115 
116     /** The exit flag. */
117     protected boolean exit = false;
118 
119     /** The batch request. */
120     protected BatchRequestDsml batchRequest;
121 
122     /** The batch response. */
123     protected BatchResponseDsml batchResponse = new BatchResponseDsml();
124 
125     protected Dsmlv2Grammar grammar = new Dsmlv2Grammar();
126 
127     /** flag to indicate to generate the response in a SOAP envelope */
128     protected boolean generateSoapResp = false;
129 
130     /** A logger for this class */
131     private static final Logger LOG = LoggerFactory.getLogger( Dsmlv2Engine.class );
132     
133     private static final String BODY_ENVELOPE = "</Body></Envelope>";
134 
135 
136     /**
137      * Creates a new instance of Dsmlv2Engine.
138      * 
139      * @param host the server host
140      * @param port the server port
141      * @param user the server admin Dn
142      * @param password the server admin's password
143      */
144     public Dsmlv2Engine( String host, int port, String user, String password )
145     {
146         this.user = user;
147         this.password = password;
148 
149         connection = new LdapNetworkConnection( host, port );
150     }
151 
152 
153     /**
154      * Creates a new instance of Dsmlv2Engine.
155      *
156      * @param connection an unbound active connection
157      * @param user the user name to be used to bind this connection to the server
158      * @param password user's credentials
159      */
160     public Dsmlv2Engine( LdapConnection connection, String user, String password )
161     {
162         this.user = user;
163         this.password = password;
164 
165         this.connection = connection;
166     }
167 
168 
169     /**
170      * Processes the file given and return the result of the operations
171      * 
172      * @param dsmlInput the DSMLv2 formatted request input
173      * @return the XML response in DSMLv2 Format
174      * @throws XmlPullParserException if an error occurs in the parser
175      */
176     public String processDSML( String dsmlInput ) throws XmlPullParserException
177     {
178         parser = new Dsmlv2Parser( grammar );
179         parser.setInput( dsmlInput );
180 
181         return processDSML();
182     }
183 
184 
185     /**
186      * Processes the file given and return the result of the operations
187      * 
188      * @param fileName the path to the file
189      * @return the XML response in DSMLv2 Format
190      * @throws XmlPullParserException if an error occurs in the parser
191      * @throws IOException if the file does not exist
192      */
193     public String processDSMLFile( String fileName ) throws XmlPullParserException, IOException
194     {
195         parser = new Dsmlv2Parser( grammar );
196         parser.setInputFile( fileName );
197 
198         return processDSML();
199     }
200 
201 
202     /**
203      * Process the given file and optionally writing the output to the
204      * output stream(if not null)
205      *
206      * @param file the DSML file
207      * @param respStream the output stream to which response will be written, skipped if null
208      * @throws Exception If the processing fails
209      */
210     public void processDSMLFile( File file, OutputStream respStream ) throws Exception
211     {
212         parser = new Dsmlv2Parser( grammar );
213         parser.setInputFile( file.getAbsolutePath() );
214 
215         processDSML( respStream );
216     }
217 
218 
219     /**
220      * Uses the default UTF-8 encoding for processing the DSML
221      * 
222      * @see #processDSML(InputStream, String, OutputStream)
223      * @param inputStream The Stream containing the DSML to process
224      * @param out The Stream where to put the result
225      * @throws Exception If we had an error while processing the DSML
226      */
227     public void processDSML( InputStream inputStream, OutputStream out ) throws Exception
228     {
229         processDSML( inputStream, "UTF-8", out );
230     }
231 
232 
233     /**
234      * Processes the DSML request(s) from the given input stream with the specified encoding
235      * and writes the response to the output stream
236      * 
237      * @param inputStream the input stream for DSML batch request
238      * @param inputEncoding encoding to be used while reading the DSML request data
239      * @param out the output stream to which DSML response will be written
240      * @throws Exception If the processing fails
241      */
242     public void processDSML( InputStream inputStream, String inputEncoding, OutputStream out ) throws Exception
243     {
244         parser = new Dsmlv2Parser( grammar );
245         parser.setInput( inputStream, inputEncoding );
246         processDSML( out );
247     }
248 
249 
250     /**
251      * Processes the Request document
252      * 
253      * @return the XML response in DSMLv2 Format
254      */
255     private String processDSML()
256     {
257         try
258         {
259             ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
260             processDSML( byteOut );
261             return new String( byteOut.toByteArray(), Charsets.UTF_8 );
262         }
263         catch ( IOException e )
264         {
265             LOG.error( I18n.err( I18n.ERR_02000_FAILED_PROCESSING_DSML ), e );
266         }
267 
268         return null;
269     }
270 
271 
272     /**
273      * Processes the DSML batch request and writes the response of each operation will be
274      * written to the given response stream if it is not null
275      *
276      * @param outStream the stream to which the responses will be written, can be null
277      * @throws IOException If we had an issue while reading or writing the data
278      */
279     protected void processDSML( OutputStream outStream ) throws IOException
280     {
281         BufferedWriter respWriter = null;
282 
283         if ( outStream != null )
284         {
285             respWriter = new BufferedWriter( new OutputStreamWriter( outStream, StandardCharsets.UTF_8 ) );
286 
287             if ( generateSoapResp )
288             {
289                 respWriter.write( "<Envelope " );
290 
291                 Namespace soapNs = new Namespace( null, "http://www.w3.org/2001/12/soap-envelope" );
292                 soapNs.write( respWriter );
293 
294                 respWriter.write( "><Body>" );
295             }
296         }
297 
298         // Binding to LDAP Server
299         try
300         {
301             bind( 1 );
302         }
303         catch ( Exception e )
304         {
305             if ( LOG.isWarnEnabled() )
306             {
307                 LOG.warn( I18n.msg( I18n.MSG_02002_FAILED_TO_BIND ), e );
308             }
309 
310             // Unable to connect to server
311             // We create a new ErrorResponse and return the XML response.
312             ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.COULD_NOT_CONNECT, e
313                 .getLocalizedMessage() );
314 
315             batchResponse.addResponse( errorResponse );
316 
317             if ( respWriter != null )
318             {
319                 respWriter.write( batchResponse.toDsml() );
320                 if ( generateSoapResp )
321                 {
322                     respWriter.write( BODY_ENVELOPE );
323                 }
324 
325                 respWriter.flush();
326             }
327 
328             return;
329         }
330 
331         // Processing BatchRequest:
332         //    - Parsing and Getting BatchRequest
333         //    - Getting and registering options from BatchRequest
334         try
335         {
336             processBatchRequest();
337         }
338         catch ( XmlPullParserException e )
339         {
340             // We create a new ErrorResponse and return the XML response.
341             ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST, I18n.err(
342                 I18n.ERR_02003_LINE_COLUMN, e.getLocalizedMessage(), e.getLineNumber(), e.getColumnNumber() ) );
343 
344             batchResponse.addResponse( errorResponse );
345 
346             if ( respWriter != null )
347             {
348                 respWriter.write( batchResponse.toDsml() );
349                 if ( generateSoapResp )
350                 {
351                     respWriter.write( BODY_ENVELOPE );
352                 }
353 
354                 respWriter.flush();
355             }
356 
357             return;
358         }
359 
360         String batchResponseTag = null;
361         
362         if ( respWriter != null )
363         {
364             StringBuilder sb = new StringBuilder();
365 
366             sb.append( "<batchResponse " );
367 
368             sb.append( ParserUtils.DSML_NAMESPACE.asXML() );
369 
370             // a space to separate the namespace declarations
371             sb.append( " " );
372 
373             sb.append( ParserUtils.XSD_NAMESPACE.asXML() );
374 
375             // a space to separate the namespace declarations
376             sb.append( " " );
377 
378             sb.append( ParserUtils.XSI_NAMESPACE.asXML() );
379 
380             sb.append( " requestID=\"" );
381             sb.append( batchRequest.getRequestID() );
382             sb.append( "\">" );
383 
384             batchResponseTag = sb.toString();
385         }
386 
387         // Processing each request:
388         //    - Getting a new request
389         //    - Checking if the request is well formed
390         //    - Sending the request to the server
391         //    - Getting and converting reponse(s) as XML
392         //    - Looping until last request
393         DsmlDecorator<? extends Request> request = null;
394 
395         try
396         {
397             request = parser.getNextRequest();
398         }
399         catch ( XmlPullParserException e )
400         {
401             if ( LOG.isWarnEnabled() )
402             {
403                 LOG.warn( I18n.msg( I18n.MSG_02000_FAILED_GETTING_NEXT_REQUEST ), e );
404             }
405 
406             int reqId = 0;
407 
408             // We create a new ErrorResponse and return the XML response.
409             ErrorResponse errorResponse = new ErrorResponse( reqId, ErrorResponseType.MALFORMED_REQUEST, I18n.err(
410                 I18n.ERR_02003_LINE_COLUMN, e.getLocalizedMessage(), e.getLineNumber(), e.getColumnNumber() ) );
411 
412             batchResponse.addResponse( errorResponse );
413 
414             if ( respWriter != null )
415             {
416                 respWriter.write( batchResponse.toDsml() );
417 
418                 if ( generateSoapResp )
419                 {
420                     respWriter.write( BODY_ENVELOPE );
421                 }
422 
423                 respWriter.flush();
424             }
425 
426             return;
427         }
428 
429         // We can now write the tag, as we don't have an error
430         if ( respWriter != null )
431         {
432             respWriter.write( batchResponseTag );
433         }
434 
435         // (Request == null when there's no more request to process)
436         while ( request != null )
437         {
438             // Checking the request has a requestID attribute if Processing = Parallel and ResponseOrder = Unordered
439             if ( ( batchRequest.getProcessing().equals( Processing.PARALLEL ) )
440                 && ( batchRequest.getResponseOrder().equals( ResponseOrder.UNORDERED ) )
441                 && ( request.getDecorated().getMessageId() <= 0 ) )
442             {
443                 // Then we have to send an errorResponse
444                 ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST, I18n
445                     .err( I18n.ERR_02004_MISSING_REQUEST_ID ) );
446 
447                 if ( respWriter != null )
448                 {
449                     writeResponse( respWriter, errorResponse );
450                 }
451                 else
452                 {
453                     batchResponse.addResponse( errorResponse );
454                 }
455 
456                 break;
457             }
458 
459             try
460             {
461                 processRequest( request, respWriter );
462             }
463             catch ( Exception e )
464             {
465                 if ( LOG.isWarnEnabled() )
466                 {
467                     LOG.warn( I18n.msg( I18n.MSG_02001_FAILED_PROCESSING_REQUEST ), e );
468                 }
469 
470                 // We create a new ErrorResponse and return the XML response.
471                 ErrorResponse errorResponse = new ErrorResponse( request.getDecorated().getMessageId(),
472                     ErrorResponseType.GATEWAY_INTERNAL_ERROR, I18n.err(
473                         I18n.ERR_02005_INTERNAL_ERROR, e.getMessage() ) );
474 
475                 if ( respWriter != null )
476                 {
477                     writeResponse( respWriter, errorResponse );
478                 }
479                 else
480                 {
481                     batchResponse.addResponse( errorResponse );
482                 }
483 
484                 break;
485             }
486 
487             // Checking if we need to exit processing (if an error has occurred if onError == Exit)
488             if ( exit )
489             {
490                 break;
491             }
492 
493             // Getting next request
494             try
495             {
496                 request = parser.getNextRequest();
497             }
498             catch ( XmlPullParserException e )
499             {
500                 // We create a new ErrorResponse and return the XML response.
501                 ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST, I18n.err(
502                     I18n.ERR_02003_LINE_COLUMN, e.getLocalizedMessage(), e.getLineNumber(), e.getColumnNumber() ) );
503 
504                 if ( respWriter != null )
505                 {
506                     writeResponse( respWriter, errorResponse );
507                 }
508                 else
509                 {
510                     batchResponse.addResponse( errorResponse );
511                 }
512 
513                 break;
514             }
515         }
516 
517         if ( respWriter != null )
518         {
519             respWriter.write( "</batchResponse>" );
520 
521             if ( generateSoapResp )
522             {
523                 respWriter.write( BODY_ENVELOPE );
524             }
525 
526             respWriter.flush();
527         }
528     }
529 
530 
531     /**
532      * Writes the response to the writer of the underlying output stream
533      * 
534      * @param respWriter The writer used to write the response
535      * @param respDsml The decorator containing the response
536      * @throws IOException If we had an error while writing the DSML response
537      */
538     protected void writeResponse( BufferedWriter respWriter, DsmlDecorator<?> respDsml ) throws IOException
539     {
540         if ( respWriter != null )
541         {
542             Element xml = respDsml.toDsml( null );
543             xml.write( respWriter );
544         }
545     }
546 
547 
548     /**
549      * @return the generateSoapResp
550      */
551     public boolean isGenerateSoapResp()
552     {
553         return generateSoapResp;
554     }
555 
556 
557     /**
558      * @param generateSoapResp the generateSoapResp to set
559      */
560     public void setGenerateSoapResp( boolean generateSoapResp )
561     {
562         this.generateSoapResp = generateSoapResp;
563     }
564 
565 
566     /**
567      * @return the batchResponse
568      */
569     public BatchResponseDsml getBatchResponse()
570     {
571         return batchResponse;
572     }
573 
574 
575     /**
576      * @return the connection
577      */
578     public LdapConnection getConnection()
579     {
580         return connection;
581     }
582 
583 
584     /**
585      * Processes a single request
586      * 
587      * @param request the request to process
588      * @param respWriter The writer used to store the DSML response
589      * @exception Exception If we had an error while processing the request
590      */
591     protected void processRequest( DsmlDecorator<? extends Request> request, BufferedWriter respWriter )
592         throws Exception
593     {
594         ResultCodeEnum resultCode = null;
595 
596         switch ( request.getDecorated().getType() )
597         {
598             case ABANDON_REQUEST:
599                 connection.abandon( ( AbandonRequest ) request );
600                 return;
601 
602             case ADD_REQUEST:
603                 AddResponse response = connection.add( ( AddRequest ) request );
604                 resultCode = response.getLdapResult().getResultCode();
605                 AddResponseDsml addResponseDsml = new AddResponseDsml( connection.getCodecService(), response );
606                 writeResponse( respWriter, addResponseDsml );
607 
608                 break;
609 
610             case BIND_REQUEST:
611                 BindResponse bindResponse = connection.bind( ( BindRequest ) request );
612                 resultCode = bindResponse.getLdapResult().getResultCode();
613                 BindResponseDsml authResponseDsml = new BindResponseDsml( connection.getCodecService(), bindResponse );
614                 writeResponse( respWriter, authResponseDsml );
615 
616                 break;
617 
618             case COMPARE_REQUEST:
619                 CompareResponse compareResponse = connection.compare( ( CompareRequest ) request );
620                 resultCode = compareResponse.getLdapResult().getResultCode();
621                 CompareResponseDsml compareResponseDsml = new CompareResponseDsml( connection.getCodecService(),
622                     compareResponse );
623                 writeResponse( respWriter, compareResponseDsml );
624 
625                 break;
626 
627             case DEL_REQUEST:
628                 DeleteResponse delResponse = connection.delete( ( DeleteRequest ) request );
629                 resultCode = delResponse.getLdapResult().getResultCode();
630                 DelResponseDsml delResponseDsml = new DelResponseDsml( connection.getCodecService(), delResponse );
631                 writeResponse( respWriter, delResponseDsml );
632 
633                 break;
634 
635             case EXTENDED_REQUEST:
636                 ExtendedResponse extendedResponse = connection.extended( ( ExtendedRequest ) request );
637                 resultCode = extendedResponse.getLdapResult().getResultCode();
638                 ExtendedResponseDsml extendedResponseDsml = new ExtendedResponseDsml( connection.getCodecService(),
639                     extendedResponse );
640                 writeResponse( respWriter, extendedResponseDsml );
641 
642                 break;
643 
644             case MODIFY_REQUEST:
645                 ModifyResponse modifyResponse = connection.modify( ( ModifyRequest ) request );
646                 resultCode = modifyResponse.getLdapResult().getResultCode();
647                 ModifyResponseDsml modifyResponseDsml = new ModifyResponseDsml( connection.getCodecService(),
648                     modifyResponse );
649                 writeResponse( respWriter, modifyResponseDsml );
650 
651                 break;
652 
653             case MODIFYDN_REQUEST:
654                 ModifyDnResponse modifyDnResponse = connection.modifyDn( ( ModifyDnRequest ) request );
655                 resultCode = modifyDnResponse.getLdapResult().getResultCode();
656                 ModDNResponseDsml modDNResponseDsml = new ModDNResponseDsml( connection.getCodecService(),
657                     modifyDnResponse );
658                 writeResponse( respWriter, modDNResponseDsml );
659 
660                 break;
661 
662             case SEARCH_REQUEST:
663                 SearchCursor searchResponses = connection.search( ( SearchRequest ) request );
664 
665                 SearchResponseDsml searchResponseDsml = new SearchResponseDsml( connection.getCodecService() );
666 
667                 if ( respWriter != null )
668                 {
669                     StringBuilder sb = new StringBuilder();
670                     sb.append( "<searchResponse" );
671 
672                     if ( request.getDecorated().getMessageId() > 0 )
673                     {
674                         sb.append( " requestID=\"" );
675                         sb.append( request.getDecorated().getMessageId() );
676                         sb.append( '"' );
677                     }
678 
679                     sb.append( '>' );
680 
681                     respWriter.write( sb.toString() );
682                 }
683 
684                 while ( searchResponses.next() )
685                 {
686                     Response searchResponse = searchResponses.get();
687 
688                     if ( searchResponse.getType() == MessageTypeEnum.SEARCH_RESULT_ENTRY )
689                     {
690                         SearchResultEntry searchResultEntry = ( SearchResultEntry ) searchResponse;
691 
692                         SearchResultEntryDsml searchResultEntryDsml = new SearchResultEntryDsml(
693                             connection.getCodecService(), searchResultEntry );
694                         searchResponseDsml = new SearchResponseDsml( connection.getCodecService(),
695                             searchResultEntryDsml );
696 
697                         if ( respWriter != null )
698                         {
699                             writeResponse( respWriter, searchResultEntryDsml );
700                         }
701                         else
702                         {
703                             searchResponseDsml.addResponse( searchResultEntryDsml );
704                         }
705                     }
706                     else if ( searchResponse.getType() == MessageTypeEnum.SEARCH_RESULT_REFERENCE )
707                     {
708                         SearchResultReference searchResultReference = ( SearchResultReference ) searchResponse;
709 
710                         SearchResultReferenceDsml searchResultReferenceDsml = new SearchResultReferenceDsml(
711                             connection.getCodecService(), searchResultReference );
712                         searchResponseDsml = new SearchResponseDsml( connection.getCodecService(),
713                             searchResultReferenceDsml );
714 
715                         if ( respWriter != null )
716                         {
717                             writeResponse( respWriter, searchResultReferenceDsml );
718                         }
719                         else
720                         {
721                             searchResponseDsml.addResponse( searchResultReferenceDsml );
722                         }
723                     }
724                 }
725 
726                 SearchResultDone srDone = searchResponses.getSearchResultDone();
727 
728                 if ( srDone != null )
729                 {
730                     resultCode = srDone.getLdapResult().getResultCode();
731 
732                     SearchResultDoneDsml srdDsml = new SearchResultDoneDsml( connection.getCodecService(), srDone );
733 
734                     if ( respWriter != null )
735                     {
736                         writeResponse( respWriter, srdDsml );
737                         respWriter.write( "</searchResponse>" );
738                     }
739                     else
740                     {
741                         searchResponseDsml.addResponse( srdDsml );
742                         batchResponse.addResponse( searchResponseDsml );
743                     }
744                 }
745 
746                 break;
747 
748             case UNBIND_REQUEST:
749                 connection.unBind();
750                 break;
751 
752             default:
753                 throw new IllegalStateException( I18n.err( I18n.ERR_02001_UNEXPECTED_REQUEST_TYPE, request.getDecorated().getType() ) );
754         }
755 
756         if ( ( !continueOnError ) && ( resultCode != null ) && ( resultCode != ResultCodeEnum.SUCCESS )
757             && ( resultCode != ResultCodeEnum.COMPARE_TRUE ) && ( resultCode != ResultCodeEnum.COMPARE_FALSE )
758             && ( resultCode != ResultCodeEnum.REFERRAL ) )
759         {
760             // Turning on Exit flag
761             exit = true;
762         }
763     }
764 
765 
766     /**
767      * Processes the BatchRequest
768      * <ul>
769      *     <li>Parsing and Getting BatchRequest</li>
770      *     <li>Getting and registering options from BatchRequest</li>
771      * </ul>
772      * 
773      * @throws XmlPullParserException if an error occurs in the parser
774      */
775     protected void processBatchRequest() throws XmlPullParserException
776     {
777         // Parsing BatchRequest
778         parser.parseBatchRequest();
779 
780         // Getting BatchRequest
781         batchRequest = parser.getBatchRequest();
782 
783         if ( OnError.RESUME.equals( batchRequest.getOnError() ) )
784         {
785             continueOnError = true;
786         }
787         else if ( OnError.EXIT.equals( batchRequest.getOnError() ) )
788         {
789             continueOnError = false;
790         }
791 
792         if ( ( batchRequest.getRequestID() != 0 ) && ( batchResponse != null ) )
793         {
794             batchResponse.setRequestID( batchRequest.getRequestID() );
795         }
796     }
797 
798 
799     /**
800      * Binds to the ldap server
801      * 
802      * @param messageId the message Id
803      * @throws LdapException If we had an issue while binding
804      * @throws IOException If we had an issue while transmitting the request or re ceiving the response
805      */
806     protected void bind( int messageId ) throws LdapException, IOException
807     {
808         if ( ( connection != null ) && connection.isAuthenticated() )
809         {
810             return;
811         }
812 
813         if ( connection == null )
814         {
815             throw new IOException( I18n.err( I18n.ERR_02002_MISSING_CONNECTION_TO_BIND ) );
816         }
817 
818         BindRequest bindRequest = new BindRequestImpl();
819         bindRequest.setSimple( true );
820         bindRequest.setCredentials( Strings.getBytesUtf8( password ) );
821         bindRequest.setName( user );
822         bindRequest.setVersion3( true );
823         bindRequest.setMessageId( messageId );
824 
825         BindResponse bindResponse = connection.bind( bindRequest );
826 
827         if ( bindResponse.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS )
828         {
829             if ( LOG.isWarnEnabled() )
830             {
831                 LOG.warn( I18n.msg( I18n.MSG_02003_ERROR, bindResponse.getLdapResult().getDiagnosticMessage() ) );
832             }
833         }
834     }
835 }