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.syncState.SyncStateTypeEnum;
36  import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValue;
37  import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateValueImpl;
38  
39  
40  /**
41   * A syncStateValue object, as defined in RFC 4533
42   *
43   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
44   */
45  public class SyncStateValueDecorator extends ControlDecorator<SyncStateValue> implements SyncStateValue
46  {
47      /** Global length for the control */
48      private int syncStateSeqLength;
49  
50      /** An instance of this decoder */
51      private static final Asn1Decoder DECODER = new Asn1Decoder();
52  
53  
54      /**
55       * Creates a new instance of SyncStateValueDecorator.
56       * 
57       * @param codec The LDAP Service to use
58       */
59      public SyncStateValueDecorator( LdapApiService codec )
60      {
61          super( codec, new SyncStateValueImpl() );
62      }
63  
64  
65      /**
66       * Creates a new instance of SyncStateValueDecorator.
67       * 
68       * @param codec The LDAP Service to use
69       * @param value The SyncState value to use
70       */
71      public SyncStateValueDecorator( LdapApiService codec, SyncStateValue value )
72      {
73          super( codec, value );
74      }
75  
76  
77      /**
78       * {@inheritDoc}
79       */
80      @Override
81      public byte[] getCookie()
82      {
83          return getDecorated().getCookie();
84      }
85  
86  
87      /**
88       * {@inheritDoc}
89       */
90      @Override
91      public void setCookie( byte[] cookie )
92      {
93          getDecorated().setCookie( cookie );
94      }
95  
96  
97      /**
98       * {@inheritDoc}
99       */
100     @Override
101     public SyncStateTypeEnum getSyncStateType()
102     {
103         return getDecorated().getSyncStateType();
104     }
105 
106 
107     /**
108      * {@inheritDoc}
109      */
110     @Override
111     public void setSyncStateType( SyncStateTypeEnum syncStateType )
112     {
113         getDecorated().setSyncStateType( syncStateType );
114     }
115 
116 
117     /**
118      * {@inheritDoc}
119      */
120     @Override
121     public byte[] getEntryUUID()
122     {
123         return getDecorated().getEntryUUID();
124     }
125 
126 
127     /**
128      * {@inheritDoc}
129      */
130     @Override
131     public void setEntryUUID( byte[] entryUUID )
132     {
133         getDecorated().setEntryUUID( entryUUID );
134     }
135 
136 
137     /**
138      * Compute the SyncStateValue length.
139      * <br>
140      * SyncStateValue :
141      * <pre>
142      * 0x30 L1
143      *  |
144      *  +--&gt; 0x0A 0x01 [0x00|0x01|0x02|0x03] (type)
145      * [+--&gt; 0x04 L2 abcd...                 (entryUUID)
146      * [+--&gt; 0x04 L3 abcd...                 (cookie)
147      * </pre>
148      * 
149      * @return The computed length
150      */
151     @Override
152     public int computeLength()
153     {
154         // The sync state type length
155         syncStateSeqLength = 1 + 1 + 1;
156 
157         syncStateSeqLength += 1 + TLV.getNbBytes( getEntryUUID().length ) + getEntryUUID().length;
158 
159         // The cookie length, if we have a cookie
160         if ( getCookie() != null )
161         {
162             syncStateSeqLength += 1 + TLV.getNbBytes( getCookie().length ) + getCookie().length;
163         }
164 
165         valueLength = 1 + TLV.getNbBytes( syncStateSeqLength ) + syncStateSeqLength;
166 
167         return valueLength;
168     }
169 
170 
171     /**
172      * Encode the SyncStateValue control
173      *
174      * @param buffer The encoded sink
175      * @return A ByteBuffer that contains the encoded PDU
176      * @throws EncoderException If anything goes wrong.
177      */
178     @Override
179     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
180     {
181         if ( buffer == null )
182         {
183             throw new EncoderException( I18n.err( I18n.ERR_04023 ) );
184         }
185 
186         // Encode the SEQ
187         buffer.put( UniversalTag.SEQUENCE.getValue() );
188         buffer.put( TLV.getBytes( syncStateSeqLength ) );
189 
190         // The mode
191         buffer.put( UniversalTag.ENUMERATED.getValue() );
192         buffer.put( ( byte ) 0x01 );
193         buffer.put( BerValue.getBytes( getSyncStateType().getValue() ) );
194 
195         // the entryUUID
196         BerValue.encode( buffer, getEntryUUID() );
197 
198         // The cookie
199         if ( getCookie() != null )
200         {
201             BerValue.encode( buffer, getCookie() );
202         }
203 
204         return buffer;
205     }
206 
207 
208     /**
209      * {@inheritDoc}
210      */
211     @Override
212     public byte[] getValue()
213     {
214         if ( value == null )
215         {
216             try
217             {
218                 computeLength();
219                 ByteBuffer buffer = ByteBuffer.allocate( valueLength );
220 
221                 // Encode the SEQ
222                 buffer.put( UniversalTag.SEQUENCE.getValue() );
223                 buffer.put( TLV.getBytes( syncStateSeqLength ) );
224 
225                 // The mode
226                 buffer.put( UniversalTag.ENUMERATED.getValue() );
227                 buffer.put( ( byte ) 0x01 );
228                 buffer.put( BerValue.getBytes( getSyncStateType().getValue() ) );
229 
230                 // the entryUUID
231                 BerValue.encode( buffer, getEntryUUID() );
232 
233                 // The cookie
234                 if ( getCookie() != null )
235                 {
236                     BerValue.encode( buffer, getCookie() );
237                 }
238 
239                 value = buffer.array();
240             }
241             catch ( Exception e )
242             {
243                 return null;
244             }
245         }
246 
247         return value;
248     }
249 
250 
251     /**
252      * {@inheritDoc}
253      */
254     @Override
255     public Asn1Object decode( byte[] controlBytes ) throws DecoderException
256     {
257         ByteBuffer bb = ByteBuffer.wrap( controlBytes );
258         SyncStateValueContainer container = new SyncStateValueContainer( this );
259         DECODER.decode( bb, container );
260         return this;
261     }
262 }