blob: 1ee238ae8ea7d370e052d29c24bd2e9e4926cc8c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.shared.ldap.codec;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import org.apache.directory.shared.asn1.AbstractAsn1Object;
import org.apache.directory.shared.asn1.ber.tlv.TLV;
import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
import org.apache.directory.shared.asn1.ber.tlv.Value;
import org.apache.directory.shared.asn1.codec.EncoderException;
import org.apache.directory.shared.i18n.I18n;
import org.apache.directory.shared.ldap.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.name.DN;
import org.apache.directory.shared.ldap.util.LdapURL;
import org.apache.directory.shared.ldap.util.StringTools;
/**
* A ldapObject to store the LdapResult
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class LdapResultCodec extends AbstractAsn1Object
{
// ~ Instance fields
// ----------------------------------------------------------------------------
/**
* The result code. The different values are :
*
* success (0),
* operationsError (1),
* protocolError (2),
* timeLimitExceeded (3),
* sizeLimitExceeded (4),
* compareFalse (5),
* compareTrue (6),
* authMethodNotSupported (7),
* strongAuthRequired (8),
* -- 9 reserved --
* referral (10),
* adminLimitExceeded (11),
* unavailableCriticalExtension (12),
* confidentialityRequired (13),
* saslBindInProgress (14),
* noSuchAttribute (16),
* undefinedAttributeType (17),
* inappropriateMatching (18),
* constraintViolation (19),
* attributeOrValueExists (20),
* invalidAttributeSyntax (21),
* -- 22-31 unused --
* noSuchObject (32),
* aliasProblem (33),
* invalidDNSyntax (34),
* -- 35 reserved for undefined isLeaf --
* aliasDereferencingProblem (36),
* -- 37-47 unused --
* inappropriateAuthentication (48),
* invalidCredentials (49),
* insufficientAccessRights (50),
* busy (51),
* unavailable (52),
* unwillingToPerform (53),
* loopDetect (54),
* -- 55-63 unused --
* namingViolation (64),
* objectClassViolation (65),
* notAllowedOnNonLeaf (66),
* notAllowedOnRDN (67),
* entryAlreadyExists (68),
* objectClassModsProhibited (69),
* -- 70 reserved for CLDAP --
* affectsMultipleDSAs (71), -- new
* -- 72-79 unused --
* other (80),
* ...
* }
*/
private ResultCodeEnum resultCode;
/** The DN that is matched by the Bind */
private DN matchedDN;
/** Temporary storage of the byte[] representing the matchedDN */
private byte[] matchedDNBytes;
/** The error message */
private String errorMessage;
/** Temporary storage for message bytes */
private byte[] errorMessageBytes;
/** The referrals, if any. This is an optional element */
private List<LdapURL> referrals;
/** The inner size of the referrals sequence */
private int referralsLength;
// ~ Constructors
// -------------------------------------------------------------------------------
/**
* Creates a new LdapResult object.
*/
public LdapResultCodec()
{
super();
}
// ~ Methods
// ------------------------------------------------------------------------------------
/**
* Initialize the referrals list
*/
public void initReferrals()
{
referrals = new ArrayList<LdapURL>();
}
/**
* Get the error message
*
* @return Returns the errorMessage.
*/
public String getErrorMessage()
{
return errorMessage;
}
/**
* Set the error message
*
* @param errorMessage The errorMessage to set.
*/
public void setErrorMessage( String errorMessage )
{
this.errorMessage = errorMessage;
}
/**
* Get the matched DN
*
* @return Returns the matchedDN.
*/
public String getMatchedDN()
{
return ( ( matchedDN == null ) ? "" : matchedDN.getNormName() );
}
/**
* Set the Matched DN
*
* @param matchedDN The matchedDN to set.
*/
public void setMatchedDN( DN matchedDN )
{
this.matchedDN = matchedDN;
}
/**
* Get the referrals
*
* @return Returns the referrals.
*/
public List<LdapURL> getReferrals()
{
return referrals;
}
/**
* Add a referral
*
* @param referral The referral to add.
*/
public void addReferral( LdapURL referral )
{
referrals.add( referral );
}
/**
* Get the result code
*
* @return Returns the resultCode.
*/
public ResultCodeEnum getResultCode()
{
return resultCode;
}
/**
* Set the result code
*
* @param resultCode The resultCode to set.
*/
public void setResultCode( ResultCodeEnum resultCode )
{
this.resultCode = resultCode;
}
/**
* Compute the LdapResult length
*
* LdapResult :
* 0x0A 01 resultCode (0..80)
* 0x04 L1 matchedDN (L1 = Length(matchedDN))
* 0x04 L2 errorMessage (L2 = Length(errorMessage))
* [0x83 L3] referrals
* |
* +--> 0x04 L4 referral
* +--> 0x04 L5 referral
* +--> ...
* +--> 0x04 Li referral
* +--> ...
* +--> 0x04 Ln referral
*
* L1 = Length(matchedDN)
* L2 = Length(errorMessage)
* L3 = n*Length(0x04) + sum(Length(L4) .. Length(Ln)) + sum(L4..Ln)
* L4..n = Length(0x04) + Length(Li) + Li
* Length(LdapResult) = Length(0x0x0A) +
* Length(0x01) + 1 + Length(0x04) + Length(L1) + L1 + Length(0x04) +
* Length(L2) + L2 + Length(0x83) + Length(L3) + L3
*/
public int computeLength()
{
int ldapResultLength = 0;
// The result code : always 3 bytes
ldapResultLength = 1 + 1 + 1;
// The matchedDN length
if ( matchedDN == null )
{
ldapResultLength += 1 + 1;
}
else
{
matchedDNBytes = StringTools.getBytesUtf8( StringTools.trimLeft( matchedDN.getName() ) );
ldapResultLength += 1 + TLV.getNbBytes( matchedDNBytes.length ) + matchedDNBytes.length;
}
// The errorMessage length
errorMessageBytes = StringTools.getBytesUtf8( errorMessage );
ldapResultLength += 1 + TLV.getNbBytes( errorMessageBytes.length ) + errorMessageBytes.length;
if ( ( referrals != null ) && ( referrals.size() != 0 ) )
{
referralsLength = 0;
// Each referral
for ( LdapURL referral:referrals )
{
referralsLength += 1 + TLV.getNbBytes( referral.getNbBytes() ) + referral.getNbBytes();
}
// The referrals
ldapResultLength += 1 + TLV.getNbBytes( referralsLength ) + referralsLength;
}
return ldapResultLength;
}
/**
* Encode the LdapResult message to a PDU.
*
* @param buffer The buffer where to put the PDU
* @return The PDU.
*/
public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
}
try
{
// The result code
buffer.put( UniversalTag.ENUMERATED_TAG );
buffer.put( ( byte ) 1 );
buffer.put( ( byte ) resultCode.getValue() );
}
catch ( BufferOverflowException boe )
{
throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
}
// The matchedDN
Value.encode( buffer, matchedDNBytes );
// The error message
Value.encode( buffer, errorMessageBytes );
// The referrals, if any
if ( ( referrals != null ) && ( referrals.size() != 0 ) )
{
// Encode the referrals sequence
// The referrals length MUST have been computed before !
buffer.put( ( byte ) LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG );
buffer.put( TLV.getBytes( referralsLength ) );
// Each referral
for ( LdapURL referral:referrals )
{
// Encode the current referral
Value.encode( buffer, referral.getBytesReference() );
}
}
return buffer;
}
/**
* Get a String representation of a LdapResult
*
* @return A LdapResult String
*/
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append( " Ldap Result\n" );
sb.append( " Result code : (" ).append( resultCode ).append( ')' );
switch ( resultCode )
{
case SUCCESS:
sb.append( " success\n" );
break;
case OPERATIONS_ERROR:
sb.append( " operationsError\n" );
break;
case PROTOCOL_ERROR:
sb.append( " protocolError\n" );
break;
case TIME_LIMIT_EXCEEDED:
sb.append( " timeLimitExceeded\n" );
break;
case SIZE_LIMIT_EXCEEDED:
sb.append( " sizeLimitExceeded\n" );
break;
case COMPARE_FALSE:
sb.append( " compareFalse\n" );
break;
case COMPARE_TRUE:
sb.append( " compareTrue\n" );
break;
case AUTH_METHOD_NOT_SUPPORTED:
sb.append( " authMethodNotSupported\n" );
break;
case STRONG_AUTH_REQUIRED:
sb.append( " strongAuthRequired\n" );
break;
case REFERRAL:
sb.append( " referral -- new\n" );
break;
case ADMIN_LIMIT_EXCEEDED:
sb.append( " adminLimitExceeded -- new\n" );
break;
case UNAVAILABLE_CRITICAL_EXTENSION:
sb.append( " unavailableCriticalExtension -- new\n" );
break;
case CONFIDENTIALITY_REQUIRED:
sb.append( " confidentialityRequired -- new\n" );
break;
case SASL_BIND_IN_PROGRESS:
sb.append( " saslBindInProgress -- new\n" );
break;
case NO_SUCH_ATTRIBUTE:
sb.append( " noSuchAttribute\n" );
break;
case UNDEFINED_ATTRIBUTE_TYPE:
sb.append( " undefinedAttributeType\n" );
break;
case INAPPROPRIATE_MATCHING:
sb.append( " inappropriateMatching\n" );
break;
case CONSTRAINT_VIOLATION:
sb.append( " constraintViolation\n" );
break;
case ATTRIBUTE_OR_VALUE_EXISTS:
sb.append( " attributeOrValueExists\n" );
break;
case INVALID_ATTRIBUTE_SYNTAX:
sb.append( " invalidAttributeSyntax\n" );
break;
case NO_SUCH_OBJECT:
sb.append( " noSuchObject\n" );
break;
case ALIAS_PROBLEM:
sb.append( " aliasProblem\n" );
break;
case INVALID_DN_SYNTAX:
sb.append( " invalidDNSyntax\n" );
break;
case ALIAS_DEREFERENCING_PROBLEM:
sb.append( " aliasDereferencingProblem\n" );
break;
case INAPPROPRIATE_AUTHENTICATION:
sb.append( " inappropriateAuthentication\n" );
break;
case INVALID_CREDENTIALS:
sb.append( " invalidCredentials\n" );
break;
case INSUFFICIENT_ACCESS_RIGHTS:
sb.append( " insufficientAccessRights\n" );
break;
case BUSY:
sb.append( " busy\n" );
break;
case UNAVAILABLE:
sb.append( " unavailable\n" );
break;
case UNWILLING_TO_PERFORM:
sb.append( " unwillingToPerform\n" );
break;
case LOOP_DETECT:
sb.append( " loopDetect\n" );
break;
case NAMING_VIOLATION:
sb.append( " namingViolation\n" );
break;
case OBJECT_CLASS_VIOLATION:
sb.append( " objectClassViolation\n" );
break;
case NOT_ALLOWED_ON_NON_LEAF:
sb.append( " notAllowedOnNonLeaf\n" );
break;
case NOT_ALLOWED_ON_RDN:
sb.append( " notAllowedOnRDN\n" );
break;
case ENTRY_ALREADY_EXISTS:
sb.append( " entryAlreadyExists\n" );
break;
case OBJECT_CLASS_MODS_PROHIBITED:
sb.append( " objectClassModsProhibited\n" );
break;
case AFFECTS_MULTIPLE_DSAS:
sb.append( " affectsMultipleDSAs -- new\n" );
break;
case OTHER:
sb.append( " other\n" );
break;
default:
switch ( resultCode.getResultCode() )
{
case 9:
sb.append( " -- 9 reserved --\n" );
break;
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
sb.append( " -- 22-31 unused --\n" );
break;
case 35 :
sb.append( " -- 35 reserved for undefined isLeaf --\n" );
break;
case 37:
case 38:
case 39:
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
sb.append( " -- 37-47 unused --\n" );
break;
case 55:
case 56:
case 57:
case 58:
case 59:
case 60:
case 61:
case 62:
case 63:
sb.append( " -- 55-63 unused --\n" );
break;
case 70:
sb.append( " -- 70 reserved for CLDAP --\n" );
break;
case 72:
case 73:
case 74:
case 75:
case 76:
case 77:
case 78:
case 79:
sb.append( " -- 72-79 unused --\n" );
break;
case 81:
case 82:
case 83:
case 84:
case 85:
case 86:
case 87:
case 88:
case 89:
case 90:
sb.append( " -- 81-90 reserved for APIs --" );
break;
default :
sb.append( "Unknown error code : " ).append( resultCode );
break;
}
break;
}
sb.append( " Matched DN : '" ).append( matchedDN == null ? "": matchedDN.toString() ).append( "'\n" );
sb.append( " Error message : '" ).append( errorMessage == null ? "" : errorMessage ).append( "'\n" );
if ( ( referrals != null ) && ( referrals.size() != 0 ) )
{
sb.append( " Referrals :\n" );
int i = 0;
for ( LdapURL referral:referrals )
{
sb.append( " Referral[" ).
append( i++ ).
append( "] :" ).
append( referral ).
append( '\n' );
}
}
return sb.toString();
}
}