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.extras.controls.ad;
21  
22  import java.nio.ByteBuffer;
23  
24  import org.apache.directory.api.asn1.Asn1Object;
25  import org.apache.directory.api.asn1.DecoderException;
26  import org.apache.directory.api.asn1.EncoderException;
27  import org.apache.directory.api.asn1.ber.Asn1Decoder;
28  import org.apache.directory.api.asn1.ber.tlv.BerValue;
29  import org.apache.directory.api.asn1.ber.tlv.TLV;
30  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
31  import org.apache.directory.api.i18n.I18n;
32  import org.apache.directory.api.ldap.codec.api.ControlDecorator;
33  import org.apache.directory.api.ldap.codec.api.LdapApiService;
34  import org.apache.directory.api.util.Strings;
35  
36  /**
37   * A decorator around AdDirSync control. It will encode and decode this control.
38   * 
39   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
40   */
41  public class AdDirSyncDecorator extends ControlDecorator<AdDirSync> implements AdDirSync
42  {
43      /** The global length for this control */
44      private int adDirSyncLength;
45  
46      /** An instance of this decoder */
47      private static final Asn1Decoder decoder = new Asn1Decoder();
48  
49  
50      /**
51       * Creates a new instance of AdDirSyncControlCodec.
52       */
53      public AdDirSyncDecorator( LdapApiService codec )
54      {
55          super( codec, new AdDirSyncImpl() );
56      }
57  
58  
59      /**
60       * Creates a new instance of AdDirSyncDecorator.
61       *
62       * @param codec The LDAP codec
63       * @param control The control to be decorated
64       */
65      public AdDirSyncDecorator( LdapApiService codec, AdDirSync control )
66      {
67          super( codec, control );
68      }
69      
70      
71      /**
72       * {@inheritDoc}
73       */
74      public int getParentFirst()
75      {
76          return getDecorated().getParentFirst();
77      }
78  
79      
80      /**
81       * {@inheritDoc}
82       */
83      public void setParentFirst( int parentFirst )
84      {
85          getDecorated().setParentFirst( parentFirst );
86      }
87      
88      
89      /**
90       * {@inheritDoc}
91       */
92      public AdDirSyncFlag getFlag()
93      {
94          return getDecorated().getFlag();
95      }
96  
97      
98      /**
99       * {@inheritDoc}
100      */
101     public void setFlag( AdDirSyncFlag flag )
102     {
103         getDecorated().setFlag( flag );
104     }
105 
106     
107     /**
108      * {@inheritDoc}
109      */
110     public int getMaxReturnLength()
111     {
112         return getDecorated().getMaxReturnLength();
113     }
114 
115     
116     /**
117      * {@inheritDoc}
118      */
119     public void setMaxReturnLength( int maxReturnLength )
120     {
121         getDecorated().setMaxReturnLength( maxReturnLength );
122     }
123     
124 
125     /**
126      * {@inheritDoc}
127      */
128     public byte[] getCookie()
129     {
130         return getDecorated().getCookie();
131     }
132 
133 
134     /**
135      * {@inheritDoc}
136      */
137     public void setCookie( byte[] cookie )
138     {
139         // Copy the bytes
140         if ( !Strings.isEmpty( cookie ) )
141         {
142             byte[] copy = new byte[cookie.length];
143             System.arraycopy( cookie, 0, copy, 0, cookie.length );
144             getDecorated().setCookie( copy );
145         }
146         else
147         {
148             getDecorated().setCookie( null );
149         }
150     }
151 
152 
153     /**
154      * Compute the AdDirSync length. We use the client side control.
155      * 0x30 L1
156      * |
157      * +--> 0x02 0x0(1-4) nnn  (parentFirst)
158      * +--> 0x02 0x0(1-4) nnn  (maxReturnLength)
159      * +--> 0x04 L2 xkcd!!!...     (cookie)
160      */
161     @Override
162     public int computeLength()
163     {
164         // the parentFirst flag length
165         adDirSyncLength = 1 + TLV.getNbBytes( getParentFirst() ) + BerValue.getNbBytes( getParentFirst() );
166 
167         // the maxReturnLength length
168         adDirSyncLength += 1 + TLV.getNbBytes( getMaxReturnLength() ) + BerValue.getNbBytes( getMaxReturnLength() );
169 
170         // cookie's length
171         byte[] cookie = getCookie();
172         
173         if ( cookie == null )
174         {
175             adDirSyncLength += 1 + 1;
176         }
177         else
178         {
179             adDirSyncLength += 1 + TLV.getNbBytes( cookie.length ) + cookie.length;
180         }
181 
182         valueLength = 1 + TLV.getNbBytes( adDirSyncLength ) + adDirSyncLength;
183 
184         // Call the super class to compute the global control length
185         return valueLength;
186     }
187 
188 
189     /**
190      * Encode the AdDirSync control. We use the client side control.
191      *
192      * @param buffer The encoded sink
193      * @return A ByteBuffer that contains the encoded PDU
194      * @throws EncoderException If anything goes wrong while encoding.
195      */
196     @Override
197     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
198     {
199         if ( buffer == null )
200         {
201             throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
202         }
203 
204         // Encode the SEQ
205         buffer.put( UniversalTag.SEQUENCE.getValue() );
206         buffer.put( TLV.getBytes( adDirSyncLength ) );
207 
208         // Encode the ParentFirst flag
209         BerValue.encode( buffer, getParentFirst() );
210 
211         // Encode the MaxReturnLength
212         BerValue.encode( buffer, getMaxReturnLength() );
213         
214         // Encode the cookie
215         BerValue.encode( buffer, getCookie() );
216 
217         return buffer;
218     }
219 
220 
221     /**
222      * {@inheritDoc}
223      */
224     @Override
225     public byte[] getValue()
226     {
227         if ( value == null )
228         {
229             try
230             {
231                 computeLength();
232                 ByteBuffer buffer = ByteBuffer.allocate( valueLength );
233 
234                 // Encode the SEQ
235                 buffer.put( UniversalTag.SEQUENCE.getValue() );
236                 buffer.put( TLV.getBytes( adDirSyncLength ) );
237 
238                 // Encode the ParentFirst flag
239                 BerValue.encode( buffer, getParentFirst() );
240 
241                 // Encode the MaxReturnLength
242                 BerValue.encode( buffer, getMaxReturnLength() );
243                 
244                 // Encode the cookie
245                 BerValue.encode( buffer, getCookie() );
246 
247                 value = buffer.array();
248             }
249             catch ( Exception e )
250             {
251                 return null;
252             }
253         }
254 
255         return value;
256     }
257     
258     
259     /**
260      * {@inheritDoc}
261      */
262     public Asn1Object decode( byte[] controlBytes ) throws DecoderException
263     {
264         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
265         AdDirSyncContainer container = new AdDirSyncContainer( getCodecService(), this );
266         decoder.decode( bb, container );
267         return this;
268     }
269 }