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 package org.apache.directory.shared.ldap.codec; 021 022 023 import java.nio.BufferOverflowException; 024 import java.nio.ByteBuffer; 025 import java.util.ArrayList; 026 import java.util.List; 027 028 import org.apache.directory.shared.asn1.AbstractAsn1Object; 029 import org.apache.directory.shared.asn1.ber.tlv.TLV; 030 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag; 031 import org.apache.directory.shared.asn1.ber.tlv.Value; 032 import org.apache.directory.shared.asn1.codec.EncoderException; 033 import org.apache.directory.shared.i18n.I18n; 034 import org.apache.directory.shared.ldap.message.ResultCodeEnum; 035 import org.apache.directory.shared.ldap.name.DN; 036 import org.apache.directory.shared.ldap.util.LdapURL; 037 import org.apache.directory.shared.ldap.util.StringTools; 038 039 040 /** 041 * A ldapObject to store the LdapResult 042 * 043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 044 * @version $Rev: 921600 $, $Date: 2010-03-10 23:37:30 +0100 (Wed, 10 Mar 2010) $, 045 */ 046 public class LdapResultCodec extends AbstractAsn1Object 047 { 048 // ~ Instance fields 049 // ---------------------------------------------------------------------------- 050 051 /** 052 * The result code. The different values are : 053 * 054 * success (0), 055 * operationsError (1), 056 * protocolError (2), 057 * timeLimitExceeded (3), 058 * sizeLimitExceeded (4), 059 * compareFalse (5), 060 * compareTrue (6), 061 * authMethodNotSupported (7), 062 * strongAuthRequired (8), 063 * -- 9 reserved -- 064 * referral (10), 065 * adminLimitExceeded (11), 066 * unavailableCriticalExtension (12), 067 * confidentialityRequired (13), 068 * saslBindInProgress (14), 069 * noSuchAttribute (16), 070 * undefinedAttributeType (17), 071 * inappropriateMatching (18), 072 * constraintViolation (19), 073 * attributeOrValueExists (20), 074 * invalidAttributeSyntax (21), 075 * -- 22-31 unused -- 076 * noSuchObject (32), 077 * aliasProblem (33), 078 * invalidDNSyntax (34), 079 * -- 35 reserved for undefined isLeaf -- 080 * aliasDereferencingProblem (36), 081 * -- 37-47 unused -- 082 * inappropriateAuthentication (48), 083 * invalidCredentials (49), 084 * insufficientAccessRights (50), 085 * busy (51), 086 * unavailable (52), 087 * unwillingToPerform (53), 088 * loopDetect (54), 089 * -- 55-63 unused -- 090 * namingViolation (64), 091 * objectClassViolation (65), 092 * notAllowedOnNonLeaf (66), 093 * notAllowedOnRDN (67), 094 * entryAlreadyExists (68), 095 * objectClassModsProhibited (69), 096 * -- 70 reserved for CLDAP -- 097 * affectsMultipleDSAs (71), -- new 098 * -- 72-79 unused -- 099 * other (80), 100 * ... 101 * } 102 */ 103 private ResultCodeEnum resultCode; 104 105 /** The DN that is matched by the Bind */ 106 private DN matchedDN; 107 108 /** Temporary storage of the byte[] representing the matchedDN */ 109 private byte[] matchedDNBytes; 110 111 /** The error message */ 112 private String errorMessage; 113 114 /** Temporary storage for message bytes */ 115 private byte[] errorMessageBytes; 116 117 /** The referrals, if any. This is an optional element */ 118 private List<LdapURL> referrals; 119 120 /** The inner size of the referrals sequence */ 121 private int referralsLength; 122 123 124 // ~ Constructors 125 // ------------------------------------------------------------------------------- 126 127 /** 128 * Creates a new LdapResult object. 129 */ 130 public LdapResultCodec() 131 { 132 super(); 133 } 134 135 136 // ~ Methods 137 // ------------------------------------------------------------------------------------ 138 139 /** 140 * Initialize the referrals list 141 */ 142 public void initReferrals() 143 { 144 referrals = new ArrayList<LdapURL>(); 145 } 146 147 /** 148 * Get the error message 149 * 150 * @return Returns the errorMessage. 151 */ 152 public String getErrorMessage() 153 { 154 return errorMessage; 155 } 156 157 158 /** 159 * Set the error message 160 * 161 * @param errorMessage The errorMessage to set. 162 */ 163 public void setErrorMessage( String errorMessage ) 164 { 165 this.errorMessage = errorMessage; 166 } 167 168 169 /** 170 * Get the matched DN 171 * 172 * @return Returns the matchedDN. 173 */ 174 public String getMatchedDN() 175 { 176 return ( ( matchedDN == null ) ? "" : matchedDN.getNormName() ); 177 } 178 179 180 /** 181 * Set the Matched DN 182 * 183 * @param matchedDN The matchedDN to set. 184 */ 185 public void setMatchedDN( DN matchedDN ) 186 { 187 this.matchedDN = matchedDN; 188 } 189 190 191 /** 192 * Get the referrals 193 * 194 * @return Returns the referrals. 195 */ 196 public List<LdapURL> getReferrals() 197 { 198 return referrals; 199 } 200 201 202 /** 203 * Add a referral 204 * 205 * @param referral The referral to add. 206 */ 207 public void addReferral( LdapURL referral ) 208 { 209 referrals.add( referral ); 210 } 211 212 213 /** 214 * Get the result code 215 * 216 * @return Returns the resultCode. 217 */ 218 public ResultCodeEnum getResultCode() 219 { 220 return resultCode; 221 } 222 223 224 /** 225 * Set the result code 226 * 227 * @param resultCode The resultCode to set. 228 */ 229 public void setResultCode( ResultCodeEnum resultCode ) 230 { 231 this.resultCode = resultCode; 232 } 233 234 235 /** 236 * Compute the LdapResult length 237 * 238 * LdapResult : 239 * 0x0A 01 resultCode (0..80) 240 * 0x04 L1 matchedDN (L1 = Length(matchedDN)) 241 * 0x04 L2 errorMessage (L2 = Length(errorMessage)) 242 * [0x83 L3] referrals 243 * | 244 * +--> 0x04 L4 referral 245 * +--> 0x04 L5 referral 246 * +--> ... 247 * +--> 0x04 Li referral 248 * +--> ... 249 * +--> 0x04 Ln referral 250 * 251 * L1 = Length(matchedDN) 252 * L2 = Length(errorMessage) 253 * L3 = n*Length(0x04) + sum(Length(L4) .. Length(Ln)) + sum(L4..Ln) 254 * L4..n = Length(0x04) + Length(Li) + Li 255 * Length(LdapResult) = Length(0x0x0A) + 256 * Length(0x01) + 1 + Length(0x04) + Length(L1) + L1 + Length(0x04) + 257 * Length(L2) + L2 + Length(0x83) + Length(L3) + L3 258 */ 259 public int computeLength() 260 { 261 int ldapResultLength = 0; 262 263 // The result code : always 3 bytes 264 ldapResultLength = 1 + 1 + 1; 265 266 // The matchedDN length 267 if ( matchedDN == null ) 268 { 269 ldapResultLength += 1 + 1; 270 } 271 else 272 { 273 matchedDNBytes = StringTools.getBytesUtf8( StringTools.trimLeft( matchedDN.getName() ) ); 274 ldapResultLength += 1 + TLV.getNbBytes( matchedDNBytes.length ) + matchedDNBytes.length; 275 } 276 277 // The errorMessage length 278 errorMessageBytes = StringTools.getBytesUtf8( errorMessage ); 279 ldapResultLength += 1 + TLV.getNbBytes( errorMessageBytes.length ) + errorMessageBytes.length; 280 281 if ( ( referrals != null ) && ( referrals.size() != 0 ) ) 282 { 283 referralsLength = 0; 284 285 // Each referral 286 for ( LdapURL referral:referrals ) 287 { 288 referralsLength += 1 + TLV.getNbBytes( referral.getNbBytes() ) + referral.getNbBytes(); 289 } 290 291 // The referrals 292 ldapResultLength += 1 + TLV.getNbBytes( referralsLength ) + referralsLength; 293 } 294 295 return ldapResultLength; 296 } 297 298 299 /** 300 * Encode the LdapResult message to a PDU. 301 * 302 * @param buffer The buffer where to put the PDU 303 * @return The PDU. 304 */ 305 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 306 { 307 if ( buffer == null ) 308 { 309 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 310 } 311 312 try 313 { 314 // The result code 315 buffer.put( UniversalTag.ENUMERATED_TAG ); 316 buffer.put( ( byte ) 1 ); 317 buffer.put( ( byte ) resultCode.getValue() ); 318 } 319 catch ( BufferOverflowException boe ) 320 { 321 throw new EncoderException( I18n.err( I18n.ERR_04005 ) ); 322 } 323 324 // The matchedDN 325 Value.encode( buffer, matchedDNBytes ); 326 327 // The error message 328 Value.encode( buffer, errorMessageBytes ); 329 330 // The referrals, if any 331 if ( ( referrals != null ) && ( referrals.size() != 0 ) ) 332 { 333 // Encode the referrals sequence 334 // The referrals length MUST have been computed before ! 335 buffer.put( ( byte ) LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG ); 336 buffer.put( TLV.getBytes( referralsLength ) ); 337 338 // Each referral 339 for ( LdapURL referral:referrals ) 340 { 341 // Encode the current referral 342 Value.encode( buffer, referral.getBytesReference() ); 343 } 344 } 345 346 return buffer; 347 } 348 349 350 /** 351 * Get a String representation of a LdapResult 352 * 353 * @return A LdapResult String 354 */ 355 public String toString() 356 { 357 StringBuffer sb = new StringBuffer(); 358 359 sb.append( " Ldap Result\n" ); 360 sb.append( " Result code : (" ).append( resultCode ).append( ')' ); 361 362 switch ( resultCode ) 363 { 364 365 case SUCCESS: 366 sb.append( " success\n" ); 367 break; 368 369 case OPERATIONS_ERROR: 370 sb.append( " operationsError\n" ); 371 break; 372 373 case PROTOCOL_ERROR: 374 sb.append( " protocolError\n" ); 375 break; 376 377 case TIME_LIMIT_EXCEEDED: 378 sb.append( " timeLimitExceeded\n" ); 379 break; 380 381 case SIZE_LIMIT_EXCEEDED: 382 sb.append( " sizeLimitExceeded\n" ); 383 break; 384 385 case COMPARE_FALSE: 386 sb.append( " compareFalse\n" ); 387 break; 388 389 case COMPARE_TRUE: 390 sb.append( " compareTrue\n" ); 391 break; 392 393 case AUTH_METHOD_NOT_SUPPORTED: 394 sb.append( " authMethodNotSupported\n" ); 395 break; 396 397 case STRONG_AUTH_REQUIRED: 398 sb.append( " strongAuthRequired\n" ); 399 break; 400 401 case REFERRAL: 402 sb.append( " referral -- new\n" ); 403 break; 404 405 case ADMIN_LIMIT_EXCEEDED: 406 sb.append( " adminLimitExceeded -- new\n" ); 407 break; 408 409 case UNAVAILABLE_CRITICAL_EXTENSION: 410 sb.append( " unavailableCriticalExtension -- new\n" ); 411 break; 412 413 case CONFIDENTIALITY_REQUIRED: 414 sb.append( " confidentialityRequired -- new\n" ); 415 break; 416 417 case SASL_BIND_IN_PROGRESS: 418 sb.append( " saslBindInProgress -- new\n" ); 419 break; 420 421 case NO_SUCH_ATTRIBUTE: 422 sb.append( " noSuchAttribute\n" ); 423 break; 424 425 case UNDEFINED_ATTRIBUTE_TYPE: 426 sb.append( " undefinedAttributeType\n" ); 427 break; 428 429 case INAPPROPRIATE_MATCHING: 430 sb.append( " inappropriateMatching\n" ); 431 break; 432 433 case CONSTRAINT_VIOLATION: 434 sb.append( " constraintViolation\n" ); 435 break; 436 437 case ATTRIBUTE_OR_VALUE_EXISTS: 438 sb.append( " attributeOrValueExists\n" ); 439 break; 440 441 case INVALID_ATTRIBUTE_SYNTAX: 442 sb.append( " invalidAttributeSyntax\n" ); 443 break; 444 445 case NO_SUCH_OBJECT: 446 sb.append( " noSuchObject\n" ); 447 break; 448 449 case ALIAS_PROBLEM: 450 sb.append( " aliasProblem\n" ); 451 break; 452 453 case INVALID_DN_SYNTAX: 454 sb.append( " invalidDNSyntax\n" ); 455 break; 456 457 case ALIAS_DEREFERENCING_PROBLEM: 458 sb.append( " aliasDereferencingProblem\n" ); 459 break; 460 461 case INAPPROPRIATE_AUTHENTICATION: 462 sb.append( " inappropriateAuthentication\n" ); 463 break; 464 465 case INVALID_CREDENTIALS: 466 sb.append( " invalidCredentials\n" ); 467 break; 468 469 case INSUFFICIENT_ACCESS_RIGHTS: 470 sb.append( " insufficientAccessRights\n" ); 471 break; 472 473 case BUSY: 474 sb.append( " busy\n" ); 475 break; 476 477 case UNAVAILABLE: 478 sb.append( " unavailable\n" ); 479 break; 480 481 case UNWILLING_TO_PERFORM: 482 sb.append( " unwillingToPerform\n" ); 483 break; 484 485 case LOOP_DETECT: 486 sb.append( " loopDetect\n" ); 487 break; 488 489 case NAMING_VIOLATION: 490 sb.append( " namingViolation\n" ); 491 break; 492 493 case OBJECT_CLASS_VIOLATION: 494 sb.append( " objectClassViolation\n" ); 495 break; 496 497 case NOT_ALLOWED_ON_NON_LEAF: 498 sb.append( " notAllowedOnNonLeaf\n" ); 499 break; 500 501 case NOT_ALLOWED_ON_RDN: 502 sb.append( " notAllowedOnRDN\n" ); 503 break; 504 505 case ENTRY_ALREADY_EXISTS: 506 sb.append( " entryAlreadyExists\n" ); 507 break; 508 509 case OBJECT_CLASS_MODS_PROHIBITED: 510 sb.append( " objectClassModsProhibited\n" ); 511 break; 512 513 case AFFECTS_MULTIPLE_DSAS: 514 sb.append( " affectsMultipleDSAs -- new\n" ); 515 break; 516 517 case OTHER: 518 sb.append( " other\n" ); 519 break; 520 521 default: 522 switch ( resultCode.getResultCode() ) 523 { 524 case 9: 525 sb.append( " -- 9 reserved --\n" ); 526 break; 527 528 case 22: 529 case 23: 530 case 24: 531 case 25: 532 case 26: 533 case 27: 534 case 28: 535 case 29: 536 case 30: 537 case 31: 538 sb.append( " -- 22-31 unused --\n" ); 539 break; 540 541 case 35 : 542 sb.append( " -- 35 reserved for undefined isLeaf --\n" ); 543 break; 544 545 case 37: 546 case 38: 547 case 39: 548 case 40: 549 case 41: 550 case 42: 551 case 43: 552 case 44: 553 case 45: 554 case 46: 555 case 47: 556 sb.append( " -- 37-47 unused --\n" ); 557 break; 558 559 case 55: 560 case 56: 561 case 57: 562 case 58: 563 case 59: 564 case 60: 565 case 61: 566 case 62: 567 case 63: 568 sb.append( " -- 55-63 unused --\n" ); 569 break; 570 571 case 70: 572 sb.append( " -- 70 reserved for CLDAP --\n" ); 573 break; 574 575 case 72: 576 case 73: 577 case 74: 578 case 75: 579 case 76: 580 case 77: 581 case 78: 582 case 79: 583 sb.append( " -- 72-79 unused --\n" ); 584 break; 585 586 case 81: 587 case 82: 588 case 83: 589 case 84: 590 case 85: 591 case 86: 592 case 87: 593 case 88: 594 case 89: 595 case 90: 596 sb.append( " -- 81-90 reserved for APIs --" ); 597 break; 598 599 default : 600 sb.append( "Unknown error code : " ).append( resultCode ); 601 break; 602 } 603 604 break; 605 } 606 607 sb.append( " Matched DN : '" ).append( matchedDN == null ? "": matchedDN.toString() ).append( "'\n" ); 608 sb.append( " Error message : '" ).append( errorMessage == null ? "" : errorMessage ).append( "'\n" ); 609 610 611 if ( ( referrals != null ) && ( referrals.size() != 0 ) ) 612 { 613 sb.append( " Referrals :\n" ); 614 int i = 0; 615 616 for ( LdapURL referral:referrals ) 617 { 618 619 sb.append( " Referral[" ). 620 append( i++ ). 621 append( "] :" ). 622 append( referral ). 623 append( '\n' ); 624 } 625 } 626 627 return sb.toString(); 628 } 629 }