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 */ 020package org.apache.directory.api.ldap.codec.decorators; 021 022 023import java.nio.BufferOverflowException; 024import java.nio.ByteBuffer; 025 026import org.apache.directory.api.asn1.EncoderException; 027import org.apache.directory.api.asn1.ber.tlv.BerValue; 028import org.apache.directory.api.asn1.ber.tlv.TLV; 029import org.apache.directory.api.i18n.I18n; 030import org.apache.directory.api.ldap.codec.api.Decorator; 031import org.apache.directory.api.ldap.codec.api.LdapApiService; 032import org.apache.directory.api.ldap.codec.api.LdapEncoder; 033import org.apache.directory.api.ldap.model.message.LdapResult; 034import org.apache.directory.api.ldap.model.message.Referral; 035import org.apache.directory.api.ldap.model.message.ResultCodeEnum; 036import org.apache.directory.api.ldap.model.name.Dn; 037import org.apache.directory.api.util.Strings; 038 039 040/** 041 * A decorator for the LdapResultResponse message 042 * 043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 044 */ 045public class LdapResultDecorator implements LdapResult, Decorator<LdapResult> 046{ 047 /** The decorated LdapResult */ 048 private final LdapResult decoratedLdapResult; 049 050 /** Temporary storage for message bytes */ 051 private byte[] errorMessageBytes; 052 053 /** Temporary storage of the byte[] representing the matchedDN */ 054 private byte[] matchedDnBytes; 055 056 /** The codec responsible for encoding and decoding this object. */ 057 private LdapApiService codec; 058 059 private static final byte[] DEFAULT_SUCCESS = new byte[] 060 { 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00 }; 061 062 063 /** 064 * Makes a LdapResult encodable. 065 * 066 * @param decoratedLdapResult the decorated LdapResult 067 */ 068 public LdapResultDecorator( LdapResult decoratedLdapResult ) 069 { 070 this.decoratedLdapResult = decoratedLdapResult; 071 } 072 073 074 /** 075 * @return The encoded Error message 076 */ 077 public byte[] getErrorMessageBytes() 078 { 079 return errorMessageBytes; 080 } 081 082 083 /** 084 * Set the encoded message's bytes 085 * @param errorMessageBytes The encoded bytes 086 */ 087 public void setErrorMessageBytes( byte[] errorMessageBytes ) 088 { 089 this.errorMessageBytes = errorMessageBytes; 090 } 091 092 093 /** 094 * Sets the encoded value for MatchedDn 095 * 096 * @param matchedDnBytes The encoded MatchedDN 097 */ 098 public void setMatchedDnBytes( byte[] matchedDnBytes ) 099 { 100 this.matchedDnBytes = matchedDnBytes; 101 } 102 103 104 /** 105 * @return the encoded MatchedDN 106 */ 107 public byte[] getMatchedDnBytes() 108 { 109 return matchedDnBytes; 110 } 111 112 113 //------------------------------------------------------------------------- 114 // The LdapResult methods 115 //------------------------------------------------------------------------- 116 117 /** 118 * {@inheritDoc} 119 */ 120 public ResultCodeEnum getResultCode() 121 { 122 return decoratedLdapResult.getResultCode(); 123 } 124 125 126 /** 127 * {@inheritDoc} 128 */ 129 public void setResultCode( ResultCodeEnum resultCode ) 130 { 131 decoratedLdapResult.setResultCode( resultCode ); 132 } 133 134 135 /** 136 * {@inheritDoc} 137 */ 138 public Dn getMatchedDn() 139 { 140 return decoratedLdapResult.getMatchedDn(); 141 } 142 143 144 /** 145 * {@inheritDoc} 146 */ 147 public void setMatchedDn( Dn dn ) 148 { 149 decoratedLdapResult.setMatchedDn( dn ); 150 } 151 152 153 /** 154 * {@inheritDoc} 155 */ 156 public String getDiagnosticMessage() 157 { 158 return decoratedLdapResult.getDiagnosticMessage(); 159 } 160 161 162 /** 163 * {@inheritDoc} 164 */ 165 public void setDiagnosticMessage( String diagnosticMessage ) 166 { 167 decoratedLdapResult.setDiagnosticMessage( diagnosticMessage ); 168 } 169 170 171 /** 172 * {@inheritDoc} 173 */ 174 public boolean isReferral() 175 { 176 return decoratedLdapResult.isReferral(); 177 } 178 179 180 /** 181 * {@inheritDoc} 182 */ 183 public Referral getReferral() 184 { 185 return decoratedLdapResult.getReferral(); 186 } 187 188 189 /** 190 * {@inheritDoc} 191 */ 192 public void setReferral( Referral referral ) 193 { 194 decoratedLdapResult.setReferral( referral ); 195 } 196 197 198 /** 199 * {@inheritDoc} 200 */ 201 public String toString() 202 { 203 return decoratedLdapResult.toString(); 204 } 205 206 207 //------------------------------------------------------------------------- 208 // The Decorator methods 209 //------------------------------------------------------------------------- 210 /** 211 * Compute the LdapResult length 212 * 213 * LdapResult : 214 * 0x0A 01 resultCode (0..80) 215 * 0x04 L1 matchedDN (L1 = Length(matchedDN)) 216 * 0x04 L2 errorMessage (L2 = Length(errorMessage)) 217 * [0x83 L3] referrals 218 * | 219 * +--> 0x04 L4 referral 220 * +--> 0x04 L5 referral 221 * +--> ... 222 * +--> 0x04 Li referral 223 * +--> ... 224 * +--> 0x04 Ln referral 225 * 226 * L1 = Length(matchedDN) 227 * L2 = Length(errorMessage) 228 * L3 = n*Length(0x04) + sum(Length(L4) .. Length(Ln)) + sum(L4..Ln) 229 * L4..n = Length(0x04) + Length(Li) + Li 230 * Length(LdapResult) = Length(0x0x0A) + 231 * Length(0x01) + 1 + Length(0x04) + Length(L1) + L1 + Length(0x04) + 232 * Length(L2) + L2 + Length(0x83) + Length(L3) + L3 233 */ 234 public int computeLength() 235 { 236 if ( decoratedLdapResult.isDefaultSuccess() ) 237 { 238 // The length of a default success PDU : 0xA0 0x01 0x00 0x04 0x00 0x04 0x00 239 return DEFAULT_SUCCESS.length; 240 } 241 242 int ldapResultLength = 0; 243 244 // The result code 245 ldapResultLength = 1 + 1 + BerValue.getNbBytes( getResultCode().getValue() ); 246 247 // The matchedDN length 248 if ( getMatchedDn() == null ) 249 { 250 ldapResultLength += 1 + 1; 251 } 252 else 253 { 254 byte[] matchedDNBytes = Strings.getBytesUtf8Ascii( Strings.trimLeft( getMatchedDn().getName() ) ); 255 ldapResultLength += 1 + TLV.getNbBytes( matchedDNBytes.length ) + matchedDNBytes.length; 256 setMatchedDnBytes( matchedDNBytes ); 257 } 258 259 // The errorMessage length 260 byte[] errorMessageBytes = Strings.getBytesUtf8Ascii( getDiagnosticMessage() ); 261 ldapResultLength += 1 + TLV.getNbBytes( errorMessageBytes.length ) + errorMessageBytes.length; 262 setErrorMessageBytes( errorMessageBytes ); 263 264 int referralLength = LdapEncoder.computeReferralLength( getReferral() ); 265 266 if ( referralLength != 0 ) 267 { 268 // The referrals 269 ldapResultLength += 1 + TLV.getNbBytes( referralLength ) + referralLength; 270 } 271 272 return ldapResultLength; 273 } 274 275 276 /** 277 * Encode the LdapResult message to a PDU. 278 * 279 * @param buffer The buffer where to put the PDU 280 * @return The PDU. 281 */ 282 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 283 { 284 if ( buffer == null ) 285 { 286 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 287 } 288 289 if ( decoratedLdapResult.isDefaultSuccess() ) 290 { 291 // The length of a default success PDU : 0xA0 0x01 0x00 0x04 0x00 0x04 0x00 292 buffer.put( DEFAULT_SUCCESS ); 293 294 return buffer; 295 } 296 297 try 298 { 299 // The result code 300 BerValue.encodeEnumerated( buffer, getResultCode().getValue() ); 301 } 302 catch ( BufferOverflowException boe ) 303 { 304 throw new EncoderException( I18n.err( I18n.ERR_04005 ) ); 305 } 306 307 // The matchedDN 308 BerValue.encode( buffer, getMatchedDnBytes() ); 309 310 // The error message 311 BerValue.encode( buffer, getErrorMessageBytes() ); 312 313 // The referrals, if any 314 Referral referral = getReferral(); 315 316 if ( referral != null ) 317 { 318 LdapEncoder.encodeReferral( buffer, referral ); 319 } 320 321 return buffer; 322 } 323 324 325 /** 326 * {@inheritDoc} 327 */ 328 public LdapResult getDecorated() 329 { 330 return decoratedLdapResult; 331 } 332 333 334 /** 335 * {@inheritDoc} 336 */ 337 public LdapApiService getCodecService() 338 { 339 return codec; 340 } 341 342 343 /** 344 * {@inheritDoc} 345 */ 346 public boolean isDefaultSuccess() 347 { 348 return decoratedLdapResult.isDefaultSuccess(); 349 } 350}