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 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.protocols.ldap; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.ArrayList; 033 import java.util.Iterator; 034 035 import org.opends.server.api.ProtocolElement; 036 import org.opends.server.protocols.asn1.ASN1Element; 037 import org.opends.server.protocols.asn1.ASN1Integer; 038 import org.opends.server.protocols.asn1.ASN1Sequence; 039 import org.opends.server.types.DebugLogLevel; 040 import org.opends.server.types.LDAPException; 041 042 import static org.opends.server.loggers.debug.DebugLogger.*; 043 import org.opends.server.loggers.debug.DebugTracer; 044 import static org.opends.messages.ProtocolMessages.*; 045 import static org.opends.server.protocols.ldap.LDAPResultCode.*; 046 import static org.opends.server.util.ServerConstants.*; 047 048 049 /** 050 * This class defines the data structures and methods to use when interacting 051 * with an LDAP message, which is the basic envelope used to hold LDAP requests 052 * and responses. 053 */ 054 public class LDAPMessage 055 implements ProtocolElement 056 { 057 /** 058 * The tracer object for the debug logger. 059 */ 060 private static final DebugTracer TRACER = getTracer(); 061 062 // The set of controls for this LDAP message. 063 private ArrayList<LDAPControl> controls; 064 065 // The message ID for this LDAP message. 066 private int messageID; 067 068 // The protocol op for this LDAP message. 069 private ProtocolOp protocolOp; 070 071 072 073 /** 074 * Creates a new LDAP message with the provided message ID and protocol op but 075 * no controls. 076 * 077 * @param messageID The message ID for this LDAP message. 078 * @param protocolOp The protocol op for this LDAP message. 079 */ 080 public LDAPMessage(int messageID, ProtocolOp protocolOp) 081 { 082 this.messageID = messageID; 083 this.protocolOp = protocolOp; 084 085 controls = new ArrayList<LDAPControl>(0); 086 } 087 088 089 090 /** 091 * Creates a new LDAP message with the provided message ID, protocol op, and 092 * set of controls. 093 * 094 * @param messageID The message ID for this LDAP message. 095 * @param protocolOp The protocol op for this LDAP message. 096 * @param controls The set of controls for this LDAP message. 097 */ 098 public LDAPMessage(int messageID, ProtocolOp protocolOp, 099 ArrayList<LDAPControl> controls) 100 { 101 this.messageID = messageID; 102 this.protocolOp = protocolOp; 103 104 if (controls == null) 105 { 106 this.controls = new ArrayList<LDAPControl>(0); 107 } 108 else 109 { 110 this.controls = controls; 111 } 112 } 113 114 115 116 /** 117 * Retrieves the message ID for this LDAP message. 118 * 119 * @return The message ID for this LDAP message. 120 */ 121 public int getMessageID() 122 { 123 return messageID; 124 } 125 126 127 128 /** 129 * Specifies the message ID for this LDAP message. 130 * 131 * @param messageID The message ID for this LDAP message. 132 */ 133 public void setMessageID(int messageID) 134 { 135 this.messageID = messageID; 136 } 137 138 139 140 /** 141 * Retrieves the protocol op for this LDAP message. 142 * 143 * @return The protocol op for this LDAP message. 144 */ 145 public ProtocolOp getProtocolOp() 146 { 147 return protocolOp; 148 } 149 150 151 152 /** 153 * Retrieves the protocol op type for this LDAP message. 154 * 155 * @return The protocol op type for this LDAP message. 156 */ 157 public byte getProtocolOpType() 158 { 159 return protocolOp.getType(); 160 } 161 162 163 164 /** 165 * Retrieves the protocol op name for this LDAP message. 166 * 167 * @return The protocol op name for this LDAP message. 168 */ 169 public String getProtocolOpName() 170 { 171 return protocolOp.getProtocolOpName(); 172 } 173 174 175 176 /** 177 * Retrieves the protocol op for this LDAP message as an abandon request 178 * protocol op. 179 * 180 * @return The protocol op for this LDAP message as an abandon request 181 * protocol op. 182 * 183 * @throws ClassCastException If the protocol op is not an abandon request 184 * protocol op. 185 */ 186 public AbandonRequestProtocolOp getAbandonRequestProtocolOp() 187 throws ClassCastException 188 { 189 return (AbandonRequestProtocolOp) protocolOp; 190 } 191 192 193 194 /** 195 * Retrieves the protocol op for this LDAP message as an add request protocol 196 * op. 197 * 198 * @return The protocol op for this LDAP message as an add request protocol 199 * op. 200 * 201 * @throws ClassCastException If the protocol op is not an add request 202 * protocol op. 203 */ 204 public AddRequestProtocolOp getAddRequestProtocolOp() 205 throws ClassCastException 206 { 207 return (AddRequestProtocolOp) protocolOp; 208 } 209 210 211 212 /** 213 * Retrieves the protocol op for this LDAP message as an add response protocol 214 * op. 215 * 216 * @return The protocol op for this LDAP message as an add response protocol 217 * op. 218 * 219 * @throws ClassCastException If the protocol op is not an add response 220 * protocol op. 221 */ 222 public AddResponseProtocolOp getAddResponseProtocolOp() 223 throws ClassCastException 224 { 225 return (AddResponseProtocolOp) protocolOp; 226 } 227 228 229 230 /** 231 * Retrieves the protocol op for this LDAP message as a bind request 232 * protocol op. 233 * 234 * @return The protocol op for this LDAP message as a bind request 235 * protocol op. 236 * 237 * @throws ClassCastException If the protocol op is not a bind request 238 * protocol op. 239 */ 240 public BindRequestProtocolOp getBindRequestProtocolOp() 241 throws ClassCastException 242 { 243 return (BindRequestProtocolOp) protocolOp; 244 } 245 246 247 248 /** 249 * Retrieves the protocol op for this LDAP message as a bind response 250 * protocol op. 251 * 252 * @return The protocol op for this LDAP message as a bind response 253 * protocol op. 254 * 255 * @throws ClassCastException If the protocol op is not a bind response 256 * protocol op. 257 */ 258 public BindResponseProtocolOp getBindResponseProtocolOp() 259 throws ClassCastException 260 { 261 return (BindResponseProtocolOp) protocolOp; 262 } 263 264 265 266 /** 267 * Retrieves the protocol op for this LDAP message as a compare request 268 * protocol op. 269 * 270 * @return The protocol op for this LDAP message as a compare request 271 * protocol op. 272 * 273 * @throws ClassCastException If the protocol op is not a compare request 274 * protocol op. 275 */ 276 public CompareRequestProtocolOp getCompareRequestProtocolOp() 277 throws ClassCastException 278 { 279 return (CompareRequestProtocolOp) protocolOp; 280 } 281 282 283 284 /** 285 * Retrieves the protocol op for this LDAP message as a compare response 286 * protocol op. 287 * 288 * @return The protocol op for this LDAP message as a compare response 289 * protocol op. 290 * 291 * @throws ClassCastException If the protocol op is not a compare response 292 * protocol op. 293 */ 294 public CompareResponseProtocolOp getCompareResponseProtocolOp() 295 throws ClassCastException 296 { 297 return (CompareResponseProtocolOp) protocolOp; 298 } 299 300 301 302 /** 303 * Retrieves the protocol op for this LDAP message as a delete request 304 * protocol op. 305 * 306 * @return The protocol op for this LDAP message as a delete request 307 * protocol op. 308 * 309 * @throws ClassCastException If the protocol op is not a delete request 310 * protocol op. 311 */ 312 public DeleteRequestProtocolOp getDeleteRequestProtocolOp() 313 throws ClassCastException 314 { 315 return (DeleteRequestProtocolOp) protocolOp; 316 } 317 318 319 320 /** 321 * Retrieves the protocol op for this LDAP message as a delete response 322 * protocol op. 323 * 324 * @return The protocol op for this LDAP message as a delete response 325 * protocol op. 326 * 327 * @throws ClassCastException If the protocol op is not a delete response 328 * protocol op. 329 */ 330 public DeleteResponseProtocolOp getDeleteResponseProtocolOp() 331 throws ClassCastException 332 { 333 return (DeleteResponseProtocolOp) protocolOp; 334 } 335 336 337 338 /** 339 * Retrieves the protocol op for this LDAP message as an extended request 340 * protocol op. 341 * 342 * @return The protocol op for this LDAP message as an extended request 343 * protocol op. 344 * 345 * @throws ClassCastException If the protocol op is not an extended request 346 * protocol op. 347 */ 348 public ExtendedRequestProtocolOp getExtendedRequestProtocolOp() 349 throws ClassCastException 350 { 351 return (ExtendedRequestProtocolOp) protocolOp; 352 } 353 354 355 356 /** 357 * Retrieves the protocol op for this LDAP message as an extended response 358 * protocol op. 359 * 360 * @return The protocol op for this LDAP message as an extended response 361 * protocol op. 362 * 363 * @throws ClassCastException If the protocol op is not an extended response 364 * protocol op. 365 */ 366 public ExtendedResponseProtocolOp getExtendedResponseProtocolOp() 367 throws ClassCastException 368 { 369 return (ExtendedResponseProtocolOp) protocolOp; 370 } 371 372 373 374 /** 375 * Retrieves the protocol op for this LDAP message as a modify request 376 * protocol op. 377 * 378 * @return The protocol op for this LDAP message as a modify request 379 * protocol op. 380 * 381 * @throws ClassCastException If the protocol op is not a modify request 382 * protocol op. 383 */ 384 public ModifyRequestProtocolOp getModifyRequestProtocolOp() 385 throws ClassCastException 386 { 387 return (ModifyRequestProtocolOp) protocolOp; 388 } 389 390 391 392 /** 393 * Retrieves the protocol op for this LDAP message as a modify response 394 * protocol op. 395 * 396 * @return The protocol op for this LDAP message as a modify response 397 * protocol op. 398 * 399 * @throws ClassCastException If the protocol op is not a modify response 400 * protocol op. 401 */ 402 public ModifyResponseProtocolOp getModifyResponseProtocolOp() 403 throws ClassCastException 404 { 405 return (ModifyResponseProtocolOp) protocolOp; 406 } 407 408 409 410 /** 411 * Retrieves the protocol op for this LDAP message as a modify DN request 412 * protocol op. 413 * 414 * @return The protocol op for this LDAP message as a modify DN request 415 * protocol op. 416 * 417 * @throws ClassCastException If the protocol op is not a modify DN request 418 * protocol op. 419 */ 420 public ModifyDNRequestProtocolOp getModifyDNRequestProtocolOp() 421 throws ClassCastException 422 { 423 return (ModifyDNRequestProtocolOp) protocolOp; 424 } 425 426 427 428 /** 429 * Retrieves the protocol op for this LDAP message as a modify DN response 430 * protocol op. 431 * 432 * @return The protocol op for this LDAP message as a modify DN response 433 * protocol op. 434 * 435 * @throws ClassCastException If the protocol op is not a modify DN response 436 * protocol op. 437 */ 438 public ModifyDNResponseProtocolOp getModifyDNResponseProtocolOp() 439 throws ClassCastException 440 { 441 return (ModifyDNResponseProtocolOp) protocolOp; 442 } 443 444 445 446 /** 447 * Retrieves the protocol op for this LDAP message as a search request 448 * protocol op. 449 * 450 * @return The protocol op for this LDAP message as a search request 451 * protocol op. 452 * 453 * @throws ClassCastException If the protocol op is not a search request 454 * protocol op. 455 */ 456 public SearchRequestProtocolOp getSearchRequestProtocolOp() 457 throws ClassCastException 458 { 459 return (SearchRequestProtocolOp) protocolOp; 460 } 461 462 463 464 /** 465 * Retrieves the protocol op for this LDAP message as a search result done 466 * protocol op. 467 * 468 * @return The protocol op for this LDAP message as a search result done 469 * protocol op. 470 * 471 * @throws ClassCastException If the protocol op is not a search result done 472 * protocol op. 473 */ 474 public SearchResultDoneProtocolOp getSearchResultDoneProtocolOp() 475 throws ClassCastException 476 { 477 return (SearchResultDoneProtocolOp) protocolOp; 478 } 479 480 481 482 /** 483 * Retrieves the protocol op for this LDAP message as a search result entry 484 * protocol op. 485 * 486 * @return The protocol op for this LDAP message as a search result entry 487 * protocol op. 488 * 489 * @throws ClassCastException If the protocol op is not a search result 490 * entry protocol op. 491 */ 492 public SearchResultEntryProtocolOp getSearchResultEntryProtocolOp() 493 throws ClassCastException 494 { 495 return (SearchResultEntryProtocolOp) protocolOp; 496 } 497 498 499 500 /** 501 * Retrieves the protocol op for this LDAP message as a search result 502 * reference protocol op. 503 * 504 * @return The protocol op for this LDAP message as a search result reference 505 * protocol op. 506 * 507 * @throws ClassCastException If the protocol op is not a search result 508 * reference protocol op. 509 */ 510 public SearchResultReferenceProtocolOp getSearchResultReferenceProtocolOp() 511 throws ClassCastException 512 { 513 return (SearchResultReferenceProtocolOp) protocolOp; 514 } 515 516 517 518 /** 519 * Retrieves the protocol op for this LDAP message as an unbind request 520 * protocol op. 521 * 522 * @return The protocol op for this LDAP message as an unbind request 523 * protocol op. 524 * 525 * @throws ClassCastException If the protocol op is not an unbind request 526 * protocol op. 527 */ 528 public UnbindRequestProtocolOp getUnbindRequestProtocolOp() 529 throws ClassCastException 530 { 531 return (UnbindRequestProtocolOp) protocolOp; 532 } 533 534 535 536 /** 537 * Specifies the protocol op for this LDAP message. 538 * 539 * @param protocolOp The protocol op for this LDAP message. 540 */ 541 public void setProtocolOp(ProtocolOp protocolOp) 542 { 543 this.protocolOp = protocolOp; 544 } 545 546 547 548 /** 549 * Retrieves the set of controls for this LDAP message. It may be modified by 550 * the caller. 551 * 552 * @return The set of controls for this LDAP message. 553 */ 554 public ArrayList<LDAPControl> getControls() 555 { 556 return controls; 557 } 558 559 560 561 /** 562 * Encodes this LDAP message to an ASN.1 element. 563 * 564 * @return The ASN.1 element containing the encoded LDAP message. 565 */ 566 public ASN1Element encode() 567 { 568 ArrayList<ASN1Element> messageElements = new ArrayList<ASN1Element>(3); 569 messageElements.add(new ASN1Integer(messageID)); 570 messageElements.add(protocolOp.encode()); 571 572 if (! controls.isEmpty()) 573 { 574 messageElements.add(LDAPControl.encodeControls(controls)); 575 } 576 577 return new ASN1Sequence(messageElements); 578 } 579 580 581 582 /** 583 * Decodes the provided ASN.1 sequence as an LDAP message. 584 * 585 * @param messageSequence The ASN.1 sequence to decode as an LDAP message. 586 * 587 * @return The decoded LDAP message. 588 * 589 * @throws LDAPException If a problem occurs while attempting to decode the 590 * LDAP message. 591 */ 592 public static LDAPMessage decode(ASN1Sequence messageSequence) 593 throws LDAPException 594 { 595 if (messageSequence == null) 596 { 597 Message message = ERR_LDAP_MESSAGE_DECODE_NULL.get(); 598 throw new LDAPException(PROTOCOL_ERROR, message); 599 } 600 601 ArrayList<ASN1Element> elements = messageSequence.elements(); 602 int numElements = elements.size(); 603 if ((numElements < 2) || (numElements > 3)) 604 { 605 Message message = 606 ERR_LDAP_MESSAGE_DECODE_INVALID_ELEMENT_COUNT.get(numElements); 607 throw new LDAPException(PROTOCOL_ERROR, message); 608 } 609 610 611 int messageID; 612 try 613 { 614 messageID = elements.get(0).decodeAsInteger().intValue(); 615 } 616 catch (Exception e) 617 { 618 if (debugEnabled()) 619 { 620 TRACER.debugCaught(DebugLogLevel.ERROR, e); 621 } 622 623 Message message = 624 ERR_LDAP_MESSAGE_DECODE_MESSAGE_ID.get(String.valueOf(e)); 625 throw new LDAPException(PROTOCOL_ERROR, message, e); 626 } 627 628 629 ProtocolOp protocolOp; 630 try 631 { 632 protocolOp = ProtocolOp.decode(elements.get(1)); 633 } 634 catch (Exception e) 635 { 636 if (debugEnabled()) 637 { 638 TRACER.debugCaught(DebugLogLevel.ERROR, e); 639 } 640 641 Message message = 642 ERR_LDAP_MESSAGE_DECODE_PROTOCOL_OP.get(String.valueOf(e)); 643 throw new LDAPException(PROTOCOL_ERROR, message, e); 644 } 645 646 647 ArrayList<LDAPControl> controls; 648 if (numElements == 3) 649 { 650 try 651 { 652 controls = LDAPControl.decodeControls(elements.get(2)); 653 } 654 catch (Exception e) 655 { 656 if (debugEnabled()) 657 { 658 TRACER.debugCaught(DebugLogLevel.ERROR, e); 659 } 660 661 Message message = 662 ERR_LDAP_MESSAGE_DECODE_CONTROLS.get(String.valueOf(e)); 663 throw new LDAPException(PROTOCOL_ERROR, message, e); 664 } 665 } 666 else 667 { 668 controls = new ArrayList<LDAPControl>(0); 669 } 670 671 672 return new LDAPMessage(messageID, protocolOp, controls); 673 } 674 675 676 677 /** 678 * Retrieves the name of the protocol associated with this protocol element. 679 * 680 * @return The name of the protocol associated with this protocol element. 681 */ 682 public String getProtocolElementName() 683 { 684 return "LDAP"; 685 } 686 687 688 689 /** 690 * Retrieves a string representation of this LDAP message. 691 * 692 * @return A string representation of this LDAP message. 693 */ 694 public String toString() 695 { 696 StringBuilder buffer = new StringBuilder(); 697 toString(buffer); 698 return buffer.toString(); 699 } 700 701 702 703 /** 704 * Appends a string representation of this protocol element to the provided 705 * buffer. 706 * 707 * @param buffer The buffer into which the string representation should be 708 * written. 709 */ 710 public void toString(StringBuilder buffer) 711 { 712 buffer.append("LDAPMessage(msgID="); 713 buffer.append(messageID); 714 buffer.append(", protocolOp="); 715 if (protocolOp != null) { 716 protocolOp.toString(buffer); 717 } else { 718 buffer.append("null"); 719 } 720 721 if (controls != null && !controls.isEmpty()) 722 { 723 buffer.append(", controls={ "); 724 725 Iterator<LDAPControl> iterator = controls.iterator(); 726 iterator.next().toString(buffer); 727 728 while (iterator.hasNext()) 729 { 730 buffer.append(", "); 731 iterator.next().toString(buffer); 732 } 733 734 buffer.append(" }"); 735 } 736 737 buffer.append(")"); 738 } 739 740 741 742 /** 743 * Appends a string representation of this protocol element to the provided 744 * buffer. 745 * 746 * @param buffer The buffer into which the string representation should be 747 * written. 748 * @param indent The number of spaces that should be used to indent the 749 * resulting string representation. 750 */ 751 public void toString(StringBuilder buffer, int indent) 752 { 753 StringBuilder indentBuf = new StringBuilder(indent); 754 for (int i=0 ; i < indent; i++) 755 { 756 indentBuf.append(' '); 757 } 758 759 buffer.append(indentBuf); 760 buffer.append("LDAP Message"); 761 buffer.append(EOL); 762 763 buffer.append(indentBuf); 764 buffer.append(" Message ID: "); 765 buffer.append(messageID); 766 buffer.append(EOL); 767 768 buffer.append(indentBuf); 769 buffer.append(" Protocol Op:"); 770 buffer.append(EOL); 771 protocolOp.toString(buffer, indent+4); 772 773 if (! controls.isEmpty()) 774 { 775 buffer.append(indentBuf); 776 buffer.append(" Controls:"); 777 778 for (LDAPControl c : controls) 779 { 780 c.toString(buffer, indent+4); 781 } 782 } 783 } 784 } 785