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