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      public SyncDoneValueDecorator( LdapApiService codec )
58      {
59          super( codec, new SyncDoneValueImpl() );
60      }
61  
62  
63      /**
64       * Creates a new instance of SyncDoneValueDecorator.
65       *
66       * @param codec The LDAP codec
67       * @param control The control to be decorated
68       */
69      public SyncDoneValueDecorator( LdapApiService codec, SyncDoneValue control )
70      {
71          super( codec, control );
72      }
73  
74  
75      /**
76       * Compute the syncDoneValue length.
77       * 0x30 L1
78       * |
79       * +--> 0x04 L2 xkcd!!!...     (cookie)
80       * +--> 0x01 0x01 [0x00|0xFF]  (refreshDeletes)
81       */
82      @Override
83      public int computeLength()
84      {
85          // cookie's length
86          if ( getCookie() != null )
87          {
88              syncDoneValueLength = 1 + TLV.getNbBytes( getCookie().length ) + getCookie().length;
89          }
90  
91          // the refreshDeletes flag length
92          if ( isRefreshDeletes() )
93          {
94              syncDoneValueLength += 1 + 1 + 1;
95          }
96  
97          valueLength = 1 + TLV.getNbBytes( syncDoneValueLength ) + syncDoneValueLength;
98  
99          // Call the super class to compute the global control length
100         return valueLength;
101     }
102 
103 
104     /**
105      * Encode the SyncDoneValue control
106      *
107      * @param buffer The encoded sink
108      * @return A ByteBuffer that contains the encoded PDU
109      * @throws EncoderException If anything goes wrong while encoding.
110      */
111     @Override
112     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
113     {
114         if ( buffer == null )
115         {
116             throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
117         }
118 
119         // Encode the SEQ
120         buffer.put( UniversalTag.SEQUENCE.getValue() );
121         buffer.put( TLV.getBytes( syncDoneValueLength ) );
122 
123         if ( getCookie() != null )
124         {
125             BerValue.encode( buffer, getCookie() );
126         }
127 
128         if ( isRefreshDeletes() )
129         {
130             BerValue.encode( buffer, isRefreshDeletes() );
131         }
132 
133         return buffer;
134     }
135 
136 
137     /**
138      * {@inheritDoc}
139      */
140     @Override
141     public byte[] getValue()
142     {
143         if ( value == null )
144         {
145             try
146             {
147                 computeLength();
148                 ByteBuffer buffer = ByteBuffer.allocate( valueLength );
149 
150                 // Encode the SEQ
151                 buffer.put( UniversalTag.SEQUENCE.getValue() );
152                 buffer.put( TLV.getBytes( syncDoneValueLength ) );
153 
154                 if ( getCookie() != null )
155                 {
156                     BerValue.encode( buffer, getCookie() );
157                 }
158 
159                 if ( isRefreshDeletes() )
160                 {
161                     BerValue.encode( buffer, isRefreshDeletes() );
162                 }
163 
164                 value = buffer.array();
165             }
166             catch ( Exception e )
167             {
168                 return null;
169             }
170         }
171 
172         return value;
173     }
174 
175 
176     /**
177      * {@inheritDoc}
178      */
179     public byte[] getCookie()
180     {
181         return getDecorated().getCookie();
182     }
183 
184 
185     /**
186      * {@inheritDoc}
187      */
188     public void setCookie( byte[] cookie )
189     {
190         // Copy the bytes
191         if ( !Strings.isEmpty( cookie ) )
192         {
193             byte[] copy = new byte[cookie.length];
194             System.arraycopy( cookie, 0, copy, 0, cookie.length );
195             getDecorated().setCookie( copy );
196         }
197         else
198         {
199             getDecorated().setCookie( null );
200         }
201     }
202 
203 
204     /**
205      * {@inheritDoc}
206      */
207     public boolean isRefreshDeletes()
208     {
209         return getDecorated().isRefreshDeletes();
210     }
211 
212 
213     /**
214      * {@inheritDoc}
215      */
216     public void setRefreshDeletes( boolean refreshDeletes )
217     {
218         getDecorated().setRefreshDeletes( refreshDeletes );
219     }
220 
221 
222     /**
223      * {@inheritDoc}
224      */
225     public Asn1Object decode( byte[] controlBytes ) throws DecoderException
226     {
227         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
228         SyncDoneValueContainer container = new SyncDoneValueContainer( getCodecService(), this );
229         decoder.decode( bb, container );
230         return this;
231     }
232 }