001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 * 
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 * 
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 * 
019 */
020
021package org.apache.directory.api.dsmlv2.engine;
022
023
024import java.io.BufferedWriter;
025import java.io.ByteArrayOutputStream;
026import java.io.File;
027import java.io.FileNotFoundException;
028import java.io.IOException;
029import java.io.InputStream;
030import java.io.OutputStream;
031import java.io.OutputStreamWriter;
032
033import org.apache.directory.api.asn1.DecoderException;
034import org.apache.directory.api.asn1.EncoderException;
035import org.apache.directory.api.dsmlv2.DsmlDecorator;
036import org.apache.directory.api.dsmlv2.Dsmlv2Parser;
037import org.apache.directory.api.dsmlv2.ParserUtils;
038import org.apache.directory.api.dsmlv2.reponse.AddResponseDsml;
039import org.apache.directory.api.dsmlv2.reponse.BatchResponseDsml;
040import org.apache.directory.api.dsmlv2.reponse.BindResponseDsml;
041import org.apache.directory.api.dsmlv2.reponse.CompareResponseDsml;
042import org.apache.directory.api.dsmlv2.reponse.DelResponseDsml;
043import org.apache.directory.api.dsmlv2.reponse.ErrorResponse;
044import org.apache.directory.api.dsmlv2.reponse.ErrorResponse.ErrorResponseType;
045import org.apache.directory.api.dsmlv2.reponse.ExtendedResponseDsml;
046import org.apache.directory.api.dsmlv2.reponse.ModDNResponseDsml;
047import org.apache.directory.api.dsmlv2.reponse.ModifyResponseDsml;
048import org.apache.directory.api.dsmlv2.reponse.SearchResponseDsml;
049import org.apache.directory.api.dsmlv2.reponse.SearchResultDoneDsml;
050import org.apache.directory.api.dsmlv2.reponse.SearchResultEntryDsml;
051import org.apache.directory.api.dsmlv2.reponse.SearchResultReferenceDsml;
052import org.apache.directory.api.dsmlv2.request.BatchRequestDsml;
053import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.OnError;
054import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.Processing;
055import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.ResponseOrder;
056import org.apache.directory.api.dsmlv2.request.Dsmlv2Grammar;
057import org.apache.directory.api.i18n.I18n;
058import org.apache.directory.api.ldap.model.cursor.SearchCursor;
059import org.apache.directory.api.ldap.model.exception.LdapException;
060import org.apache.directory.api.ldap.model.message.AbandonRequest;
061import org.apache.directory.api.ldap.model.message.AddRequest;
062import org.apache.directory.api.ldap.model.message.AddResponse;
063import org.apache.directory.api.ldap.model.message.BindRequest;
064import org.apache.directory.api.ldap.model.message.BindRequestImpl;
065import org.apache.directory.api.ldap.model.message.BindResponse;
066import org.apache.directory.api.ldap.model.message.CompareRequest;
067import org.apache.directory.api.ldap.model.message.CompareResponse;
068import org.apache.directory.api.ldap.model.message.DeleteRequest;
069import org.apache.directory.api.ldap.model.message.DeleteResponse;
070import org.apache.directory.api.ldap.model.message.ExtendedRequest;
071import org.apache.directory.api.ldap.model.message.ExtendedResponse;
072import org.apache.directory.api.ldap.model.message.MessageTypeEnum;
073import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
074import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
075import org.apache.directory.api.ldap.model.message.ModifyRequest;
076import org.apache.directory.api.ldap.model.message.ModifyResponse;
077import org.apache.directory.api.ldap.model.message.Request;
078import org.apache.directory.api.ldap.model.message.Response;
079import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
080import org.apache.directory.api.ldap.model.message.SearchRequest;
081import org.apache.directory.api.ldap.model.message.SearchResultDone;
082import org.apache.directory.api.ldap.model.message.SearchResultEntry;
083import org.apache.directory.api.ldap.model.message.SearchResultReference;
084import org.apache.directory.api.util.Strings;
085import org.apache.directory.ldap.client.api.LdapConnection;
086import org.apache.directory.ldap.client.api.LdapNetworkConnection;
087import org.dom4j.Element;
088import org.dom4j.Namespace;
089import org.slf4j.Logger;
090import org.slf4j.LoggerFactory;
091import org.xmlpull.v1.XmlPullParserException;
092
093
094/**
095 * This is the DSMLv2Engine. It can be use to execute operations on a LDAP Server and get the results of these operations.
096 * The format used for request and responses is the DSMLv2 format.
097 *
098 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
099 */
100public 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}