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