001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.protocols.internal; 028 029 030 031 import java.io.OutputStream; 032 import java.io.IOException; 033 import java.util.ArrayList; 034 035 import org.opends.messages.Message; 036 import org.opends.server.core.*; 037 import org.opends.server.protocols.asn1.ASN1Element; 038 import org.opends.server.protocols.ldap.*; 039 import org.opends.server.types.AuthenticationType; 040 import org.opends.server.types.Control; 041 import org.opends.server.types.SearchResultEntry; 042 import org.opends.server.types.SearchResultReference; 043 044 import static org.opends.messages.ProtocolMessages.*; 045 import static org.opends.server.protocols.ldap.LDAPConstants.*; 046 import static org.opends.server.util.ServerConstants.*; 047 048 049 050 /** 051 * This class provides an implementation of a 052 * {@code java.io.OutputStream} that can be used to facilitate 053 * internal communication with the Directory Server. On the backend, 054 * data written to this output stream will be first decoded as an 055 * ASN.1 element and then as an LDAP message. That LDAP message will 056 * be converted to an internal operation which will then be processed 057 * and the result returned to the client via the input stream on the 058 * other side of the associated internal LDAP socket. 059 */ 060 @org.opends.server.types.PublicAPI( 061 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, 062 mayInstantiate=false, 063 mayExtend=false, 064 mayInvoke=true) 065 public final class InternalLDAPOutputStream 066 extends OutputStream 067 implements InternalSearchListener 068 { 069 // Indicates whether this stream has been closed. 070 private boolean closed; 071 072 // Indicates whether the type of the ASN.1 element is needed. 073 private boolean needType; 074 075 // The BER type for the ASN.1 element being read. 076 private byte elementType; 077 078 // The data for the ASN.1 element being read. 079 private byte[] elementBytes; 080 081 // The length bytes for the ASN.1 element being read. 082 private byte[] lengthBytes; 083 084 // The offset in the appropriate array at which we should begin 085 // writing data. This could either refer to the length or data 086 // array, depending on the stage of the encoding process. 087 private int arrayOffset; 088 089 // The internal LDAP socket with which this output stream is 090 // associated. 091 private InternalLDAPSocket socket; 092 093 094 095 /** 096 * Creates a new instance of an internal LDAP output stream that is 097 * associated with the provided internal LDAP socket. 098 * 099 * @param socket The internal LDAP socket that will be serviced by 100 * this internal LDAP output stream. 101 */ 102 public InternalLDAPOutputStream(InternalLDAPSocket socket) 103 { 104 this.socket = socket; 105 106 closed = false; 107 108 needType = true; 109 elementType = 0x00; 110 elementBytes = null; 111 lengthBytes = null; 112 arrayOffset = 0; 113 } 114 115 116 117 /** 118 * Closes this output stream, its associated socket, and the 119 * socket's associated input stream. 120 */ 121 @Override() 122 public void close() 123 { 124 socket.close(); 125 } 126 127 128 129 /** 130 * Closes this output stream through an internal mechanism that will 131 * not cause an infinite recursion loop by trying to also close the 132 * output stream. 133 */ 134 @org.opends.server.types.PublicAPI( 135 stability=org.opends.server.types.StabilityLevel.PRIVATE, 136 mayInstantiate=false, 137 mayExtend=false, 138 mayInvoke=false) 139 void closeInternal() 140 { 141 closed = true; 142 } 143 144 145 146 /** 147 * Flushes this output stream and forces any buffered data to be 148 * written out. This will have no effect, since this output 149 * stream implementation does not use buffering. 150 */ 151 @Override() 152 public void flush() 153 { 154 // No implementation is required. 155 } 156 157 158 159 /** 160 * Writes the contents of the provided byte array to this output 161 * stream. 162 * 163 * @param b The byte array to be written. 164 * 165 * @throws IOException If the output stream is closed, or if there 166 * is a problem with the data being written. 167 */ 168 @Override() 169 public void write(byte[] b) 170 throws IOException 171 { 172 write(b, 0, b.length); 173 } 174 175 176 177 /** 178 * Writes the specified portion of the data in the provided byte 179 * array to this output stream. Any data written will be 180 * accumulated until a complete ASN.1 element is available, at which 181 * point it will be decoded as an LDAP message and converted to an 182 * internal operation that will be processed. 183 * 184 * @param b The byte array containing the data to be read. 185 * @param off The position in the array at which to start reading 186 * data. 187 * @param len The number of bytes to read from the array. 188 * 189 * @throws IOException If the output stream is closed, or if there 190 * is a problem with the data being written. 191 */ 192 @Override() 193 public synchronized void write(byte[] b, int off, int len) 194 throws IOException 195 { 196 if (closed) 197 { 198 Message m = ERR_INTERNALOS_CLOSED.get(); 199 throw new IOException(m.toString()); 200 } 201 202 if (len == 0) 203 { 204 return; 205 } 206 207 208 // See if we need to read the BER type. 209 int position = off; 210 int remaining = len; 211 if (needType) 212 { 213 elementType = b[position++]; 214 needType = false; 215 216 if (--remaining <= 0) 217 { 218 return; 219 } 220 } 221 222 223 // See if we need to read the first length byte. 224 if ((lengthBytes == null) && (elementBytes == null)) 225 { 226 int length = b[position++]; 227 if (length == (length & 0x7F)) 228 { 229 // It's a single-byte length, so we can create the value 230 // array. 231 elementBytes = new byte[length]; 232 } 233 else 234 { 235 // It's a multi-byte length, so we can create the length 236 // array. 237 lengthBytes = new byte[length & 0x7F]; 238 } 239 240 arrayOffset = 0; 241 if (--remaining <= 0) 242 { 243 return; 244 } 245 } 246 247 248 // See if we need to continue reading part of a multi-byte length. 249 if (lengthBytes != null) 250 { 251 // See if we have enough to read the full length. If so, then 252 // do it. Otherwise, read what we can and return. 253 int needed = lengthBytes.length - arrayOffset; 254 if (remaining >= needed) 255 { 256 System.arraycopy(b, position, lengthBytes, arrayOffset, 257 needed); 258 position += needed; 259 remaining -= needed; 260 261 int length = 0; 262 for (byte lb : lengthBytes) 263 { 264 length <<= 8; 265 length |= (lb & 0xFF); 266 } 267 268 elementBytes = new byte[length]; 269 lengthBytes = null; 270 arrayOffset = 0; 271 if (remaining <= 0) 272 { 273 return; 274 } 275 } 276 else 277 { 278 System.arraycopy(b, position, lengthBytes, arrayOffset, 279 remaining); 280 arrayOffset += remaining; 281 return; 282 } 283 } 284 285 286 // See if we need to read data for the element value. 287 if (elementBytes != null) 288 { 289 // See if we have enough to read the full value. If so, then 290 // do it, create the element, and process it. Otherwise, read 291 // what we can and return. 292 int needed = elementBytes.length - arrayOffset; 293 if (remaining >= needed) 294 { 295 System.arraycopy(b, position, elementBytes, arrayOffset, 296 needed); 297 position += needed; 298 remaining -= needed; 299 processElement(new ASN1Element(elementType, elementBytes)); 300 301 needType = true; 302 arrayOffset = 0; 303 lengthBytes = null; 304 elementBytes = null; 305 } 306 else 307 { 308 System.arraycopy(b, position, lengthBytes, arrayOffset, 309 remaining); 310 arrayOffset += remaining; 311 return; 312 } 313 } 314 315 316 // If there is still more data available, then call this method 317 // again to process it. 318 if (remaining > 0) 319 { 320 write(b, position, remaining); 321 } 322 } 323 324 325 326 /** 327 * Writes a single byte of data to this output stream. If the byte 328 * written completes an ASN.1 element that was in progress, then it 329 * will be decoded as an LDAP message and converted to an internal 330 * operation that will be processed. Otherwise, the data will be 331 * accumulated until a complete element can be formed. 332 * 333 * @param b The byte to be written. 334 * 335 * @throws IOException If the output stream is closed, or if there 336 * is a problem with the data being written. 337 */ 338 @Override() 339 public synchronized void write(int b) 340 throws IOException 341 { 342 if (closed) 343 { 344 Message m = ERR_INTERNALOS_CLOSED.get(); 345 throw new IOException(m.toString()); 346 } 347 348 if (needType) 349 { 350 elementType = (byte) (b & 0xFF); 351 needType = false; 352 return; 353 } 354 else if (elementBytes != null) 355 { 356 // The byte should be part of the element value. 357 elementBytes[arrayOffset++] = (byte) (b & 0xFF); 358 if (arrayOffset == elementBytes.length) 359 { 360 // The element has been completed, so process it. 361 processElement(new ASN1Element(elementType, elementBytes)); 362 } 363 364 lengthBytes = null; 365 elementBytes = null; 366 arrayOffset = 0; 367 needType = true; 368 369 return; 370 } 371 else if (lengthBytes != null) 372 { 373 // The byte should be part of a multi-byte length. 374 lengthBytes[arrayOffset++] = (byte) (b & 0xFF); 375 if (arrayOffset == lengthBytes.length) 376 { 377 int length = 0; 378 for (int i=0; i < lengthBytes.length; i++) 379 { 380 length <<= 8; 381 length |= (lengthBytes[i] & 0xFF); 382 } 383 384 elementBytes = new byte[length]; 385 lengthBytes = null; 386 arrayOffset = 0; 387 } 388 389 return; 390 } 391 else 392 { 393 if ((b & 0x7F) == b) 394 { 395 // It's the complete length. 396 elementBytes = new byte[b]; 397 lengthBytes = null; 398 arrayOffset = 0; 399 } 400 else 401 { 402 lengthBytes = new byte[b & 0x7F]; 403 elementBytes = null; 404 arrayOffset = 0; 405 } 406 407 return; 408 } 409 } 410 411 412 413 /** 414 * Processes the provided ASN.1 element by decoding it as an LDAP 415 * message, converting that to an internal operation, and sending 416 * the appropriate response message(s) to the client through the 417 * corresponding internal LDAP input stream. 418 * 419 * @param element The ASN.1 element to be processed. 420 * 421 * @throws IOException If a problem occurs while attempting to 422 * decode the provided ASN.1 element as an 423 * LDAP message. 424 */ 425 private void processElement(ASN1Element element) 426 throws IOException 427 { 428 LDAPMessage message; 429 try 430 { 431 message = LDAPMessage.decode(element.decodeAsSequence()); 432 } 433 catch (Exception e) 434 { 435 throw new IOException(e.getMessage()); 436 } 437 438 switch (message.getProtocolOpType()) 439 { 440 case OP_TYPE_ABANDON_REQUEST: 441 // No action is required. 442 return; 443 444 case OP_TYPE_ADD_REQUEST: 445 processAddOperation(message); 446 break; 447 448 case OP_TYPE_BIND_REQUEST: 449 processBindOperation(message); 450 break; 451 452 case OP_TYPE_COMPARE_REQUEST: 453 processCompareOperation(message); 454 break; 455 456 457 case OP_TYPE_DELETE_REQUEST: 458 processDeleteOperation(message); 459 break; 460 461 462 case OP_TYPE_EXTENDED_REQUEST: 463 processExtendedOperation(message); 464 break; 465 466 467 case OP_TYPE_MODIFY_REQUEST: 468 processModifyOperation(message); 469 break; 470 471 472 case OP_TYPE_MODIFY_DN_REQUEST: 473 processModifyDNOperation(message); 474 break; 475 476 477 case OP_TYPE_SEARCH_REQUEST: 478 processSearchOperation(message); 479 break; 480 481 482 case OP_TYPE_UNBIND_REQUEST: 483 socket.close(); 484 break; 485 486 487 default: 488 Message m = ERR_INTERNALOS_INVALID_REQUEST.get( 489 message.getProtocolElementName()); 490 throw new IOException(m.toString()); 491 } 492 } 493 494 495 496 /** 497 * Processes the content of the provided LDAP message as an add 498 * operation and returns the appropriate result to the client. 499 * 500 * @param message The LDAP message containing the request to 501 * process. 502 * 503 * @throws IOException If a problem occurs while attempting to 504 * process the operation. 505 */ 506 private void processAddOperation(LDAPMessage message) 507 throws IOException 508 { 509 int messageID = message.getMessageID(); 510 AddRequestProtocolOp request = message.getAddRequestProtocolOp(); 511 512 ArrayList<Control> requestControls = new ArrayList<Control>(); 513 if (message.getControls() != null) 514 { 515 for (LDAPControl c : message.getControls()) 516 { 517 requestControls.add(c.getControl()); 518 } 519 } 520 521 InternalClientConnection conn = socket.getConnection(); 522 AddOperationBasis op = 523 new AddOperationBasis(conn, conn.nextOperationID(), 524 messageID, requestControls, 525 request.getDN(), 526 request.getAttributes()); 527 op.run(); 528 529 AddResponseProtocolOp addResponse = 530 new AddResponseProtocolOp(op.getResultCode().getIntValue(), 531 op.getErrorMessage().toMessage(), 532 op.getMatchedDN(), 533 op.getReferralURLs()); 534 ArrayList<LDAPControl> responseControls = 535 new ArrayList<LDAPControl>(); 536 for (Control c : op.getResponseControls()) 537 { 538 responseControls.add(new LDAPControl(c)); 539 } 540 541 socket.getInputStream().addLDAPMessage( 542 new LDAPMessage(messageID, addResponse, responseControls)); 543 } 544 545 546 547 /** 548 * Processes the content of the provided LDAP message as a bind 549 * operation and returns the appropriate result to the client. 550 * 551 * @param message The LDAP message containing the request to 552 * process. 553 * 554 * @throws IOException If a problem occurs while attempting to 555 * process the operation. 556 */ 557 private void processBindOperation(LDAPMessage message) 558 throws IOException 559 { 560 int messageID = message.getMessageID(); 561 BindRequestProtocolOp request = 562 message.getBindRequestProtocolOp(); 563 564 if (request.getAuthenticationType() == AuthenticationType.SASL) 565 { 566 Message m = ERR_INTERNALOS_SASL_BIND_NOT_SUPPORTED.get(); 567 BindResponseProtocolOp bindResponse = 568 new BindResponseProtocolOp( 569 LDAPResultCode.UNWILLING_TO_PERFORM, m); 570 socket.getInputStream().addLDAPMessage( 571 new LDAPMessage(messageID, bindResponse)); 572 return; 573 } 574 575 ArrayList<Control> requestControls = new ArrayList<Control>(); 576 if (message.getControls() != null) 577 { 578 for (LDAPControl c : message.getControls()) 579 { 580 requestControls.add(c.getControl()); 581 } 582 } 583 584 InternalClientConnection conn = socket.getConnection(); 585 BindOperationBasis op = 586 new BindOperationBasis(conn, conn.nextOperationID(), 587 messageID, requestControls, 588 String.valueOf(request.getProtocolVersion()), 589 request.getDN(), request.getSimplePassword()); 590 op.run(); 591 592 BindResponseProtocolOp bindResponse = 593 new BindResponseProtocolOp(op.getResultCode().getIntValue(), 594 op.getErrorMessage().toMessage(), 595 op.getMatchedDN(), 596 op.getReferralURLs()); 597 ArrayList<LDAPControl> responseControls = 598 new ArrayList<LDAPControl>(); 599 for (Control c : op.getResponseControls()) 600 { 601 responseControls.add(new LDAPControl(c)); 602 } 603 604 if (bindResponse.getResultCode() == LDAPResultCode.SUCCESS) 605 { 606 socket.setConnection(new InternalClientConnection( 607 op.getAuthenticationInfo())); 608 } 609 610 socket.getInputStream().addLDAPMessage( 611 new LDAPMessage(messageID, bindResponse, responseControls)); 612 } 613 614 615 616 /** 617 * Processes the content of the provided LDAP message as a compare 618 * operation and returns the appropriate result to the client. 619 * 620 * @param message The LDAP message containing the request to 621 * process. 622 * 623 * @throws IOException If a problem occurs while attempting to 624 * process the operation. 625 */ 626 private void processCompareOperation(LDAPMessage message) 627 throws IOException 628 { 629 int messageID = message.getMessageID(); 630 CompareRequestProtocolOp request = 631 message.getCompareRequestProtocolOp(); 632 633 ArrayList<Control> requestControls = new ArrayList<Control>(); 634 if (message.getControls() != null) 635 { 636 for (LDAPControl c : message.getControls()) 637 { 638 requestControls.add(c.getControl()); 639 } 640 } 641 642 InternalClientConnection conn = socket.getConnection(); 643 CompareOperationBasis op = 644 new CompareOperationBasis(conn, conn.nextOperationID(), 645 messageID, requestControls, request.getDN(), 646 request.getAttributeType(), 647 request.getAssertionValue()); 648 op.run(); 649 650 CompareResponseProtocolOp compareResponse = 651 new CompareResponseProtocolOp( 652 op.getResultCode().getIntValue(), 653 op.getErrorMessage().toMessage(), 654 op.getMatchedDN(), 655 op.getReferralURLs()); 656 ArrayList<LDAPControl> responseControls = 657 new ArrayList<LDAPControl>(); 658 for (Control c : op.getResponseControls()) 659 { 660 responseControls.add(new LDAPControl(c)); 661 } 662 663 socket.getInputStream().addLDAPMessage( 664 new LDAPMessage(messageID, compareResponse, 665 responseControls)); 666 } 667 668 669 670 /** 671 * Processes the content of the provided LDAP message as a delete 672 * operation and returns the appropriate result to the client. 673 * 674 * @param message The LDAP message containing the request to 675 * process. 676 * 677 * @throws IOException If a problem occurs while attempting to 678 * process the operation. 679 */ 680 private void processDeleteOperation(LDAPMessage message) 681 throws IOException 682 { 683 int messageID = message.getMessageID(); 684 DeleteRequestProtocolOp request = 685 message.getDeleteRequestProtocolOp(); 686 687 ArrayList<Control> requestControls = new ArrayList<Control>(); 688 if (message.getControls() != null) 689 { 690 for (LDAPControl c : message.getControls()) 691 { 692 requestControls.add(c.getControl()); 693 } 694 } 695 696 InternalClientConnection conn = socket.getConnection(); 697 DeleteOperationBasis op = 698 new DeleteOperationBasis(conn, conn.nextOperationID(), 699 messageID, requestControls, request.getDN()); 700 op.run(); 701 702 DeleteResponseProtocolOp deleteResponse = 703 new DeleteResponseProtocolOp( 704 op.getResultCode().getIntValue(), 705 op.getErrorMessage().toMessage(), 706 op.getMatchedDN(), 707 op.getReferralURLs()); 708 ArrayList<LDAPControl> responseControls = 709 new ArrayList<LDAPControl>(); 710 for (Control c : op.getResponseControls()) 711 { 712 responseControls.add(new LDAPControl(c)); 713 } 714 715 socket.getInputStream().addLDAPMessage( 716 new LDAPMessage(messageID, deleteResponse, 717 responseControls)); 718 } 719 720 721 722 /** 723 * Processes the content of the provided LDAP message as an extended 724 * operation and returns the appropriate result to the client. 725 * 726 * @param message The LDAP message containing the request to 727 * process. 728 * 729 * @throws IOException If a problem occurs while attempting to 730 * process the operation. 731 */ 732 private void processExtendedOperation(LDAPMessage message) 733 throws IOException 734 { 735 int messageID = message.getMessageID(); 736 ExtendedRequestProtocolOp request = 737 message.getExtendedRequestProtocolOp(); 738 if (request.getOID().equals(OID_START_TLS_REQUEST)) 739 { 740 Message m = ERR_INTERNALOS_STARTTLS_NOT_SUPPORTED.get(); 741 ExtendedResponseProtocolOp extendedResponse = 742 new ExtendedResponseProtocolOp( 743 LDAPResultCode.UNWILLING_TO_PERFORM, m); 744 socket.getInputStream().addLDAPMessage( 745 new LDAPMessage(messageID, extendedResponse)); 746 return; 747 } 748 749 ArrayList<Control> requestControls = new ArrayList<Control>(); 750 if (message.getControls() != null) 751 { 752 for (LDAPControl c : message.getControls()) 753 { 754 requestControls.add(c.getControl()); 755 } 756 } 757 758 InternalClientConnection conn = socket.getConnection(); 759 ExtendedOperationBasis op = 760 new ExtendedOperationBasis(conn, conn.nextOperationID(), 761 messageID, requestControls, request.getOID(), 762 request.getValue()); 763 op.run(); 764 765 ExtendedResponseProtocolOp extendedResponse = 766 new ExtendedResponseProtocolOp( 767 op.getResultCode().getIntValue(), 768 op.getErrorMessage().toMessage(), 769 op.getMatchedDN(), 770 op.getReferralURLs(), op.getResponseOID(), 771 op.getResponseValue()); 772 ArrayList<LDAPControl> responseControls = 773 new ArrayList<LDAPControl>(); 774 for (Control c : op.getResponseControls()) 775 { 776 responseControls.add(new LDAPControl(c)); 777 } 778 779 socket.getInputStream().addLDAPMessage( 780 new LDAPMessage(messageID, extendedResponse, 781 responseControls)); 782 } 783 784 785 786 /** 787 * Processes the content of the provided LDAP message as a modify 788 * operation and returns the appropriate result to the client. 789 * 790 * @param message The LDAP message containing the request to 791 * process. 792 * 793 * @throws IOException If a problem occurs while attempting to 794 * process the operation. 795 */ 796 private void processModifyOperation(LDAPMessage message) 797 throws IOException 798 { 799 int messageID = message.getMessageID(); 800 ModifyRequestProtocolOp request = 801 message.getModifyRequestProtocolOp(); 802 803 ArrayList<Control> requestControls = new ArrayList<Control>(); 804 if (message.getControls() != null) 805 { 806 for (LDAPControl c : message.getControls()) 807 { 808 requestControls.add(c.getControl()); 809 } 810 } 811 812 InternalClientConnection conn = socket.getConnection(); 813 ModifyOperationBasis op = 814 new ModifyOperationBasis(conn, conn.nextOperationID(), 815 messageID, requestControls, request.getDN(), 816 request.getModifications()); 817 op.run(); 818 819 ModifyResponseProtocolOp modifyResponse = 820 new ModifyResponseProtocolOp( 821 op.getResultCode().getIntValue(), 822 op.getErrorMessage().toMessage(), 823 op.getMatchedDN(), 824 op.getReferralURLs()); 825 ArrayList<LDAPControl> responseControls = 826 new ArrayList<LDAPControl>(); 827 for (Control c : op.getResponseControls()) 828 { 829 responseControls.add(new LDAPControl(c)); 830 } 831 832 socket.getInputStream().addLDAPMessage( 833 new LDAPMessage(messageID, modifyResponse, 834 responseControls)); 835 } 836 837 838 839 /** 840 * Processes the content of the provided LDAP message as a modify DN 841 * operation and returns the appropriate result to the client. 842 * 843 * @param message The LDAP message containing the request to 844 * process. 845 * 846 * @throws IOException If a problem occurs while attempting to 847 * process the operation. 848 */ 849 private void processModifyDNOperation(LDAPMessage message) 850 throws IOException 851 { 852 int messageID = message.getMessageID(); 853 ModifyDNRequestProtocolOp request = 854 message.getModifyDNRequestProtocolOp(); 855 856 ArrayList<Control> requestControls = new ArrayList<Control>(); 857 if (message.getControls() != null) 858 { 859 for (LDAPControl c : message.getControls()) 860 { 861 requestControls.add(c.getControl()); 862 } 863 } 864 865 InternalClientConnection conn = socket.getConnection(); 866 ModifyDNOperationBasis op = 867 new ModifyDNOperationBasis(conn, conn.nextOperationID(), 868 messageID, requestControls, request.getEntryDN(), 869 request.getNewRDN(), request.deleteOldRDN(), 870 request.getNewSuperior()); 871 op.run(); 872 873 ModifyDNResponseProtocolOp modifyDNResponse = 874 new ModifyDNResponseProtocolOp( 875 op.getResultCode().getIntValue(), 876 op.getErrorMessage().toMessage(), 877 op.getMatchedDN(), 878 op.getReferralURLs()); 879 ArrayList<LDAPControl> responseControls = 880 new ArrayList<LDAPControl>(); 881 for (Control c : op.getResponseControls()) 882 { 883 responseControls.add(new LDAPControl(c)); 884 } 885 886 socket.getInputStream().addLDAPMessage( 887 new LDAPMessage(messageID, modifyDNResponse, 888 responseControls)); 889 } 890 891 892 893 /** 894 * Processes the content of the provided LDAP message as a search 895 * operation and returns the appropriate result to the client. 896 * 897 * @param message The LDAP message containing the request to 898 * process. 899 * 900 * @throws IOException If a problem occurs while attempting to 901 * process the operation. 902 */ 903 private void processSearchOperation(LDAPMessage message) 904 throws IOException 905 { 906 int messageID = message.getMessageID(); 907 SearchRequestProtocolOp request = 908 message.getSearchRequestProtocolOp(); 909 910 ArrayList<Control> requestControls = new ArrayList<Control>(); 911 if (message.getControls() != null) 912 { 913 for (LDAPControl c : message.getControls()) 914 { 915 requestControls.add(c.getControl()); 916 } 917 } 918 919 InternalClientConnection conn = socket.getConnection(); 920 InternalSearchOperation op = 921 new InternalSearchOperation(conn, conn.nextOperationID(), 922 messageID, requestControls, request.getBaseDN(), 923 request.getScope(), request.getDereferencePolicy(), 924 request.getSizeLimit(), request.getTimeLimit(), 925 request.getTypesOnly(), request.getFilter(), 926 request.getAttributes(), this); 927 op.run(); 928 929 SearchResultDoneProtocolOp searchDone = 930 new SearchResultDoneProtocolOp( 931 op.getResultCode().getIntValue(), 932 op.getErrorMessage().toMessage(), 933 op.getMatchedDN(), 934 op.getReferralURLs()); 935 ArrayList<LDAPControl> responseControls = 936 new ArrayList<LDAPControl>(); 937 for (Control c : op.getResponseControls()) 938 { 939 responseControls.add(new LDAPControl(c)); 940 } 941 942 socket.getInputStream().addLDAPMessage( 943 new LDAPMessage(messageID, searchDone, responseControls)); 944 } 945 946 947 948 /** 949 * Performs any processing necessary for the provided search result 950 * entry. 951 * 952 * @param searchOperation The internal search operation being 953 * processed. 954 * @param searchEntry The matching search result entry to be 955 * processed. 956 */ 957 @org.opends.server.types.PublicAPI( 958 stability=org.opends.server.types.StabilityLevel.PRIVATE, 959 mayInstantiate=false, 960 mayExtend=false, 961 mayInvoke=false) 962 public void handleInternalSearchEntry( 963 InternalSearchOperation searchOperation, 964 SearchResultEntry searchEntry) 965 { 966 ArrayList<LDAPControl> entryControls = 967 new ArrayList<LDAPControl>(); 968 for (Control c : searchEntry.getControls()) 969 { 970 entryControls.add(new LDAPControl(c)); 971 } 972 973 SearchResultEntryProtocolOp entry = 974 new SearchResultEntryProtocolOp(searchEntry); 975 976 socket.getInputStream().addLDAPMessage( 977 new LDAPMessage(searchOperation.getMessageID(), entry, 978 entryControls)); 979 } 980 981 982 983 /** 984 * Performs any processing necessary for the provided search result 985 * reference. 986 * 987 * @param searchOperation The internal search operation being 988 * processed. 989 * @param searchReference The search result reference to be 990 * processed. 991 */ 992 @org.opends.server.types.PublicAPI( 993 stability=org.opends.server.types.StabilityLevel.PRIVATE, 994 mayInstantiate=false, 995 mayExtend=false, 996 mayInvoke=false) 997 public void handleInternalSearchReference( 998 InternalSearchOperation searchOperation, 999 SearchResultReference searchReference) 1000 { 1001 ArrayList<LDAPControl> entryControls = 1002 new ArrayList<LDAPControl>(); 1003 for (Control c : searchReference.getControls()) 1004 { 1005 entryControls.add(new LDAPControl(c)); 1006 } 1007 1008 SearchResultReferenceProtocolOp reference = 1009 new SearchResultReferenceProtocolOp(searchReference); 1010 1011 socket.getInputStream().addLDAPMessage( 1012 new LDAPMessage(searchOperation.getMessageID(), reference, 1013 entryControls)); 1014 } 1015 1016 1017 1018 /** 1019 * Retrieves a string representation of this internal LDAP socket. 1020 * 1021 * @return A string representation of this internal LDAP socket. 1022 */ 1023 @Override() 1024 public String toString() 1025 { 1026 return "InternalLDAPOutputStream"; 1027 } 1028 } 1029