View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.codec.decorators;
21  
22  
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  
26  import org.apache.directory.api.asn1.EncoderException;
27  import org.apache.directory.api.asn1.ber.tlv.BerValue;
28  import org.apache.directory.api.asn1.ber.tlv.TLV;
29  import org.apache.directory.api.i18n.I18n;
30  import org.apache.directory.api.ldap.codec.api.Decorator;
31  import org.apache.directory.api.ldap.codec.api.LdapApiService;
32  import org.apache.directory.api.ldap.codec.api.LdapEncoder;
33  import org.apache.directory.api.ldap.model.message.LdapResult;
34  import org.apache.directory.api.ldap.model.message.Referral;
35  import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
36  import org.apache.directory.api.ldap.model.name.Dn;
37  import org.apache.directory.api.util.Strings;
38  
39  
40  /**
41   * A decorator for the LdapResultResponse message
42   *
43   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
44   */
45  public class LdapResultDecorator implements LdapResult, Decorator<LdapResult>
46  {
47      /** The decorated LdapResult */
48      private final LdapResult decoratedLdapResult;
49  
50      /** Temporary storage for message bytes */
51      private byte[] errorMessageBytes;
52  
53      /** Temporary storage of the byte[] representing the matchedDN */
54      private byte[] matchedDnBytes;
55  
56      /** The codec responsible for encoding and decoding this object. */
57      private LdapApiService codec;
58  
59      private static final byte[] DEFAULT_SUCCESS = new byte[]
60          { 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00 };
61  
62  
63      /**
64       * Makes a LdapResult encodable.
65       *
66       * @param codec The LDAP service instance
67       * @param decoratedLdapResult the decorated LdapResult
68       */
69      public LdapResultDecorator( LdapApiService codec, LdapResult decoratedLdapResult )
70      {
71          this.decoratedLdapResult = decoratedLdapResult;
72          this.codec = codec;
73      }
74  
75  
76      //-------------------------------------------------------------------------
77      // The LdapResult methods
78      //-------------------------------------------------------------------------
79  
80      /**
81       * {@inheritDoc}
82       */
83      @Override
84      public ResultCodeEnum getResultCode()
85      {
86          return decoratedLdapResult.getResultCode();
87      }
88  
89  
90      /**
91       * {@inheritDoc}
92       */
93      @Override
94      public void setResultCode( ResultCodeEnum resultCode )
95      {
96          decoratedLdapResult.setResultCode( resultCode );
97      }
98  
99  
100     /**
101      * {@inheritDoc}
102      */
103     @Override
104     public Dn getMatchedDn()
105     {
106         return decoratedLdapResult.getMatchedDn();
107     }
108 
109 
110     /**
111      * {@inheritDoc}
112      */
113     @Override
114     public void setMatchedDn( Dn dn )
115     {
116         decoratedLdapResult.setMatchedDn( dn );
117     }
118 
119 
120     /**
121      * {@inheritDoc}
122      */
123     @Override
124     public String getDiagnosticMessage()
125     {
126         return decoratedLdapResult.getDiagnosticMessage();
127     }
128 
129 
130     /**
131      * {@inheritDoc}
132      */
133     @Override
134     public void setDiagnosticMessage( String diagnosticMessage )
135     {
136         decoratedLdapResult.setDiagnosticMessage( diagnosticMessage );
137     }
138 
139 
140     /**
141      * {@inheritDoc}
142      */
143     @Override
144     public boolean isReferral()
145     {
146         return decoratedLdapResult.isReferral();
147     }
148 
149 
150     /**
151      * {@inheritDoc}
152      */
153     @Override
154     public Referral getReferral()
155     {
156         return decoratedLdapResult.getReferral();
157     }
158 
159 
160     /**
161      * {@inheritDoc}
162      */
163     @Override
164     public void setReferral( Referral referral )
165     {
166         decoratedLdapResult.setReferral( referral );
167     }
168 
169 
170     /**
171      * {@inheritDoc}
172      */
173     @Override
174     public String toString()
175     {
176         return decoratedLdapResult.toString();
177     }
178 
179 
180     //-------------------------------------------------------------------------
181     // The Decorator methods
182     //-------------------------------------------------------------------------
183     /**
184      * Compute the LdapResult length 
185      * <br>
186      * LdapResult :
187      * <pre> 
188      *   0x0A 01 resultCode (0..80)
189      *   0x04 L1 matchedDN (L1 = Length(matchedDN)) 
190      *   0x04 L2 errorMessage (L2 = Length(errorMessage)) 
191      *   [0x83 L3] referrals 
192      *     | 
193      *     +--&gt; 0x04 L4 referral 
194      *     +--&gt; 0x04 L5 referral 
195      *     +--&gt; ... 
196      *     +--&gt; 0x04 Li referral 
197      *     +--&gt; ... 
198      *     +--&gt; 0x04 Ln referral 
199      *     
200      * L1 = Length(matchedDN) 
201      * L2 = Length(errorMessage) 
202      * L3 = n*Length(0x04) + sum(Length(L4) .. Length(Ln)) + sum(L4..Ln) 
203      * L4..n = Length(0x04) + Length(Li) + Li 
204      * Length(LdapResult) = Length(0x0x0A) +
205      *      Length(0x01) + 1 + Length(0x04) + Length(L1) + L1 + Length(0x04) +
206      *      Length(L2) + L2 + Length(0x83) + Length(L3) + L3
207      * </pre>
208      */
209     @Override
210     public int computeLength()
211     {
212         if ( decoratedLdapResult.isDefaultSuccess() )
213         {
214             // The length of a default success PDU : 0xA0 0x01 0x00 0x04 0x00 0x04 0x00
215             return DEFAULT_SUCCESS.length;
216         }
217 
218         int ldapResultLength;
219 
220         // The result code
221         ldapResultLength = 1 + 1 + BerValue.getNbBytes( getResultCode().getValue() );
222 
223         // The matchedDN length
224         if ( getMatchedDn() == null )
225         {
226             ldapResultLength += 1 + 1;
227         }
228         else
229         {
230             matchedDnBytes = Strings.getBytesUtf8Ascii( Strings.trimLeft( getMatchedDn().getName() ) );
231             ldapResultLength += 1 + TLV.getNbBytes( matchedDnBytes.length ) + matchedDnBytes.length;
232         }
233 
234         // The errorMessage length
235         errorMessageBytes = Strings.getBytesUtf8Ascii( getDiagnosticMessage() );
236         ldapResultLength += 1 + TLV.getNbBytes( errorMessageBytes.length ) + errorMessageBytes.length;
237 
238         int referralLength = LdapEncoder.computeReferralLength( getReferral() );
239 
240         if ( referralLength != 0 )
241         {
242             // The referrals
243             ldapResultLength += 1 + TLV.getNbBytes( referralLength ) + referralLength;
244         }
245 
246         return ldapResultLength;
247     }
248 
249 
250     /**
251      * Encode the LdapResult message to a PDU.
252      * 
253      * @param buffer The buffer where to put the PDU
254      * @return The PDU.
255      */
256     @Override
257     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
258     {
259         if ( buffer == null )
260         {
261             throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
262         }
263 
264         if ( decoratedLdapResult.isDefaultSuccess() )
265         {
266             // The length of a default success PDU : 0xA0 0x01 0x00 0x04 0x00 0x04 0x00
267             buffer.put( DEFAULT_SUCCESS );
268 
269             return buffer;
270         }
271 
272         try
273         {
274             // The result code
275             BerValue.encodeEnumerated( buffer, getResultCode().getValue() );
276         }
277         catch ( BufferOverflowException boe )
278         {
279             throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe );
280         }
281 
282         // The matchedDN
283         BerValue.encode( buffer, matchedDnBytes );
284 
285         // The error message
286         BerValue.encode( buffer, errorMessageBytes );
287 
288         // The referrals, if any
289         Referral referral = getReferral();
290 
291         if ( referral != null )
292         {
293             LdapEncoder.encodeReferral( buffer, referral );
294         }
295 
296         return buffer;
297     }
298 
299 
300     /**
301      * {@inheritDoc}
302      */
303     @Override
304     public LdapResult getDecorated()
305     {
306         return decoratedLdapResult;
307     }
308 
309 
310     /**
311      * {@inheritDoc}
312      */
313     @Override
314     public LdapApiService getCodecService()
315     {
316         return codec;
317     }
318 
319 
320     /**
321      * {@inheritDoc}
322      */
323     @Override
324     public boolean isDefaultSuccess()
325     {
326         return decoratedLdapResult.isDefaultSuccess();
327     }
328 }