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