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.extended.ads_impl.gracefulDisconnect;
21  
22  
23  import java.nio.ByteBuffer;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import org.apache.directory.api.asn1.DecoderException;
28  import org.apache.directory.api.asn1.EncoderException;
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.ExtendedResponseDecorator;
34  import org.apache.directory.api.ldap.codec.api.LdapApiService;
35  import org.apache.directory.api.ldap.extras.extended.gracefulDisconnect.GracefulDisconnectResponse;
36  import org.apache.directory.api.ldap.model.message.Referral;
37  import org.apache.directory.api.util.Strings;
38  import org.slf4j.Logger;
39  import org.slf4j.LoggerFactory;
40  
41  
42  /**
43   * A Decorator for CancelResponses.
44   *
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   */
47  public class GracefulDisconnectResponseDecorator extends ExtendedResponseDecorator<GracefulDisconnectResponse>
48      implements GracefulDisconnectResponse
49  {
50      /** The logger. */
51      private static final Logger LOG = LoggerFactory.getLogger( GracefulDisconnectResponseDecorator.class );
52  
53      /** Length of the sequence */
54      private int gracefulDisconnectSequenceLength;
55  
56      /** Length of the replicated contexts */
57      private int replicatedContextsLength;
58      
59      /** The encoded LDAP URL list */
60      private List<byte[]> ldapUrlBytes;
61  
62      private GracefulDisconnectResponse gracefulDisconnectResponse;
63  
64      /**
65       * Creates a new instance of CancelResponseDecorator.
66       *
67       * @param codec
68       * @param decoratedMessage
69       */
70      public GracefulDisconnectResponseDecorator( LdapApiService codec, GracefulDisconnectResponse decoratedMessage )
71      {
72          super( codec, decoratedMessage );
73          gracefulDisconnectResponse = decoratedMessage;
74      }
75  
76      
77      // ------------------------------------------------------------------------
78      // ExtendedResponse Interface Method Implementations
79      // ------------------------------------------------------------------------
80      /**
81       * Gets the response OID specific encoded response values.
82       * 
83       * @return the response specific encoded response values.
84       */
85      public byte[] getResponseValue()
86      {
87          if ( responseValue == null )
88          {
89              try
90              {
91                  responseValue = encodeInternal().array();
92              }
93              catch ( EncoderException e )
94              {
95                  LOG.error( I18n.err( I18n.ERR_04164 ), e );
96                  throw new RuntimeException( e );
97              }
98          }
99  
100         return responseValue;
101     }
102 
103 
104     /**
105      * Sets the response OID specific encoded response values.
106      * 
107      * @param responseValue the response specific encoded response values.
108      */
109     public void setResponseValue( byte[] responseValue )
110     {
111         GracefulDisconnectDecoder decoder = new GracefulDisconnectDecoder();
112 
113         try
114         {
115             if ( responseValue != null )
116             {
117                 decoder.decode( responseValue );
118                 this.responseValue = new byte[responseValue.length];
119                 System.arraycopy( responseValue, 0, this.responseValue, 0, responseValue.length );
120             }
121             else
122             {
123                 this.responseValue = null;
124             }
125         }
126         catch ( DecoderException e )
127         {
128             LOG.error( I18n.err( I18n.ERR_04172 ), e );
129         }
130     }
131 
132 
133     /**
134      * {@inheritDoc}
135      */
136     public int getDelay()
137     {
138         return gracefulDisconnectResponse.getDelay();
139     }
140 
141 
142     /**
143      * {@inheritDoc}
144      */
145     public void setDelay( int delay )
146     {
147         gracefulDisconnectResponse.setDelay( delay );
148     }
149 
150 
151     /**
152      * {@inheritDoc}
153      */
154     public int getTimeOffline()
155     {
156         return gracefulDisconnectResponse.getTimeOffline();
157     }
158 
159 
160     /**
161      * {@inheritDoc}
162      */
163     public void setTimeOffline( int timeOffline )
164     {
165         gracefulDisconnectResponse.setTimeOffline( timeOffline );
166     }
167 
168 
169     /**
170      * {@inheritDoc}
171      */
172     public Referral getReplicatedContexts()
173     {
174         return gracefulDisconnectResponse.getReplicatedContexts();
175     }
176     
177     
178     /**
179      * {@inheritDoc}
180      */
181     public void addReplicatedContexts( String replicatedContext )
182     {
183         gracefulDisconnectResponse.getReplicatedContexts().addLdapUrl( replicatedContext );
184     }
185 
186 
187     /**
188      * Compute the GracefulDisconnect length 
189      * <pre>
190      * 0x30 L1 
191      *   | 
192      *   +--> [ 0x02 0x0(1-4) [0..720] ] 
193      *   +--> [ 0x80 0x0(1-3) [0..86400] ] 
194      *   +--> [ 0x30 L2 
195      *           | 
196      *           +--> (0x04 L3 value) + ]
197      * </pre>
198      */
199     /* no qualifier */ int computeLengthInternal()
200     {
201         gracefulDisconnectSequenceLength = 0;
202 
203         if ( gracefulDisconnectResponse.getTimeOffline() != 0 )
204         {
205             gracefulDisconnectSequenceLength += 1 + 1 + BerValue.getNbBytes( gracefulDisconnectResponse.getTimeOffline() );
206         }
207 
208         if ( gracefulDisconnectResponse.getDelay() != 0 )
209         {
210             gracefulDisconnectSequenceLength += 1 + 1 + BerValue.getNbBytes( gracefulDisconnectResponse.getDelay() );
211         }
212 
213         if ( ( gracefulDisconnectResponse.getReplicatedContexts() != null ) &&
214             ( gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls().size() != 0 ) )
215         {
216             replicatedContextsLength = 0;
217             
218             ldapUrlBytes = new ArrayList<byte[]>( gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls().size() );
219 
220             // We may have more than one reference.
221             for ( String replicatedContext : gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls() )
222             {
223                 byte[] bytes = Strings.getBytesUtf8( replicatedContext );
224                 ldapUrlBytes.add( bytes );
225                 int ldapUrlLength = bytes.length;
226                 replicatedContextsLength += 1 + TLV.getNbBytes( ldapUrlLength ) + ldapUrlLength;
227             }
228 
229             gracefulDisconnectSequenceLength += 1 + TLV.getNbBytes( replicatedContextsLength )
230                 + replicatedContextsLength;
231         }
232 
233         return 1 + TLV.getNbBytes( gracefulDisconnectSequenceLength ) + gracefulDisconnectSequenceLength;
234     }
235 
236 
237     /**
238      * Encodes the gracefulDisconnect extended operation.
239      * 
240      * @return A ByteBuffer that contains the encoded PDU
241      * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
242      */
243     /* no qualifier */ ByteBuffer encodeInternal() throws EncoderException
244     {
245         // Allocate the bytes buffer.
246         ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
247 
248 
249         bb.put( UniversalTag.SEQUENCE.getValue() );
250         bb.put( TLV.getBytes( gracefulDisconnectSequenceLength ) );
251 
252         if ( gracefulDisconnectResponse.getTimeOffline() != 0 )
253         {
254             BerValue.encode( bb, gracefulDisconnectResponse.getTimeOffline() );
255         }
256 
257         if ( gracefulDisconnectResponse.getDelay() != 0 )
258         {
259             bb.put( ( byte ) GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG );
260             bb.put( ( byte ) TLV.getNbBytes( gracefulDisconnectResponse.getDelay() ) );
261             bb.put( BerValue.getBytes( gracefulDisconnectResponse.getDelay() ) );
262         }
263 
264         if ( ( gracefulDisconnectResponse.getReplicatedContexts() != null ) &&
265              ( gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls().size() != 0 ) )
266         {
267             bb.put( UniversalTag.SEQUENCE.getValue() );
268             bb.put( TLV.getBytes( replicatedContextsLength ) );
269 
270             // We may have more than one reference.
271             for ( byte[] replicatedContext : ldapUrlBytes )
272             {
273                 BerValue.encode( bb, replicatedContext );
274             }
275         }
276 
277         return bb;
278     }
279 
280 
281     /**
282      * Return a string representation of the graceful disconnect
283      */
284     public String toString()
285     {
286         StringBuffer sb = new StringBuffer();
287 
288         sb.append( "Graceful Disconnect extended operation" );
289         sb.append( "    TimeOffline : " ).append( gracefulDisconnectResponse.getTimeOffline() ).append( '\n' );
290         sb.append( "    Delay : " ).append( gracefulDisconnectResponse.getDelay() ).append( '\n' );
291 
292         if ( ( gracefulDisconnectResponse.getReplicatedContexts() != null ) && ( gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls().size() != 0 ) )
293         {
294             sb.append( "    Replicated contexts :" );
295 
296             // We may have more than one reference.
297             for ( String url : gracefulDisconnectResponse.getReplicatedContexts().getLdapUrls() )
298             {
299                 sb.append( "\n        " ).append( url );
300             }
301         }
302 
303         return sb.toString();
304     }
305 }