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