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