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