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