001/*
002 *   Licensed to the Apache Software Foundation (ASF) under one
003 *   or more contributor license agreements.  See the NOTICE file
004 *   distributed with this work for additional information
005 *   regarding copyright ownership.  The ASF licenses this file
006 *   to you under the Apache License, Version 2.0 (the
007 *   "License"); you may not use this file except in compliance
008 *   with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *   Unless required by applicable law or agreed to in writing,
013 *   software distributed under the License is distributed on an
014 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *   KIND, either express or implied.  See the License for the
016 *   specific language governing permissions and limitations
017 *   under the License.
018 *
019 */
020package org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulShutdown;
021
022
023import java.nio.ByteBuffer;
024
025import org.apache.directory.api.asn1.DecoderException;
026import org.apache.directory.api.asn1.EncoderException;
027import org.apache.directory.api.asn1.ber.tlv.BerValue;
028import org.apache.directory.api.asn1.ber.tlv.TLV;
029import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
030import org.apache.directory.api.i18n.I18n;
031import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator;
032import org.apache.directory.api.ldap.codec.api.LdapApiService;
033import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulActionConstants;
034import org.apache.directory.api.ldap.extras.extended.gracefulShutdown.GracefulShutdownRequest;
035import org.slf4j.Logger;
036import org.slf4j.LoggerFactory;
037
038
039/**
040 * A Decorator for GracefulShutdownRequests.
041 *
042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043 */
044public class GracefulShutdownRequestDecorator extends ExtendedRequestDecorator<GracefulShutdownRequest>
045    implements GracefulShutdownRequest
046{
047    private static final Logger LOG = LoggerFactory.getLogger( GracefulShutdownRequestDecorator.class );
048
049    /** Length of the sequence */
050    private int gracefulSequenceLength;
051
052    private GracefulShutdownRequest gracefulShutdownRequest;
053
054
055    /**
056     * Creates a new instance of GracefulShutdownRequestDecorator.
057     *
058     * @param codec The LDAP Service to use
059     * @param decoratedMessage The GracefulShutdownRequest control to decorate
060     */
061    public GracefulShutdownRequestDecorator( LdapApiService codec, GracefulShutdownRequest decoratedMessage )
062    {
063        super( codec, decoratedMessage );
064        gracefulShutdownRequest = decoratedMessage;
065    }
066
067
068    /**
069     * {@inheritDoc}
070     */
071    @Override
072    public void setRequestValue( byte[] requestValue )
073    {
074        GracefulShutdownDecoder decoder = new GracefulShutdownDecoder();
075
076        try
077        {
078            if ( requestValue != null )
079            {
080                gracefulShutdownRequest = decoder.decode( requestValue );
081
082                this.requestValue = new byte[requestValue.length];
083                System.arraycopy( requestValue, 0, this.requestValue, 0, requestValue.length );
084            }
085            else
086            {
087                this.requestValue = null;
088            }
089        }
090        catch ( DecoderException e )
091        {
092            LOG.error( I18n.err( I18n.ERR_04165 ), e );
093            throw new RuntimeException( e );
094        }
095    }
096
097
098    /**
099     * {@inheritDoc}
100     */
101    @Override
102    public byte[] getRequestValue()
103    {
104        if ( requestValue == null )
105        {
106            try
107            {
108                requestValue = encodeInternal().array();
109            }
110            catch ( EncoderException e )
111            {
112                LOG.error( I18n.err( I18n.ERR_04164 ), e );
113                throw new RuntimeException( e );
114            }
115        }
116
117        return requestValue;
118    }
119
120
121    /**
122     * {@inheritDoc}
123     */
124    @Override
125    public int getDelay()
126    {
127        return getDecorated().getDelay();
128    }
129
130
131    /**
132     * {@inheritDoc}
133     */
134    @Override
135    public void setDelay( int delay )
136    {
137        getDecorated().setDelay( delay );
138    }
139
140
141    /**
142     * {@inheritDoc}
143     */
144    @Override
145    public int getTimeOffline()
146    {
147        return getDecorated().getTimeOffline();
148    }
149
150
151    /**
152     * {@inheritDoc}
153     */
154    @Override
155    public void setTimeOffline( int timeOffline )
156    {
157        getDecorated().setTimeOffline( timeOffline );
158    }
159
160
161    /**
162     * Compute the GracefulShutdown length 
163     * 
164     * <pre>
165     * 0x30 L1 
166     *   | 
167     *   +--&gt; [0x02 0x0(1-4) [0..720] ] 
168     *   +--&gt; [0x80 0x0(1-3) [0..86400] ] 
169     * </pre>  
170     * L1 will always be &lt; 11.
171     */
172    /* no qualifier */int computeLengthInternal()
173    {
174        int gracefulLength = 1 + 1;
175        gracefulSequenceLength = 0;
176
177        if ( gracefulShutdownRequest.getTimeOffline() != 0 )
178        {
179            gracefulSequenceLength += 1 + 1 + BerValue.getNbBytes( gracefulShutdownRequest.getTimeOffline() );
180        }
181
182        if ( gracefulShutdownRequest.getDelay() != 0 )
183        {
184            gracefulSequenceLength += 1 + 1 + BerValue.getNbBytes( gracefulShutdownRequest.getDelay() );
185        }
186
187        return gracefulLength + gracefulSequenceLength;
188    }
189
190
191    /**
192     * Encodes the gracefulShutdown extended operation.
193     * 
194     * @return A ByteBuffer that contains the encoded PDU
195     * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong.
196     */
197    /* no qualifier */ByteBuffer encodeInternal() throws EncoderException
198    {
199        // Allocate the bytes buffer.
200        ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() );
201
202        bb.put( UniversalTag.SEQUENCE.getValue() );
203        bb.put( TLV.getBytes( gracefulSequenceLength ) );
204
205        if ( gracefulShutdownRequest.getTimeOffline() != 0 )
206        {
207            BerValue.encode( bb, gracefulShutdownRequest.getTimeOffline() );
208        }
209
210        if ( gracefulShutdownRequest.getDelay() != 0 )
211        {
212            bb.put( ( byte ) GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG );
213            bb.put( ( byte ) BerValue.getNbBytes( gracefulShutdownRequest.getDelay() ) );
214            bb.put( BerValue.getBytes( gracefulShutdownRequest.getDelay() ) );
215        }
216        return bb;
217    }
218
219
220    /**
221     * Return a string representation of the graceful shutdown
222     */
223    @Override
224    public String toString()
225    {
226        StringBuilder sb = new StringBuilder();
227
228        sb.append( "Graceful Shutdown extended operation" );
229        sb.append( "    TimeOffline : " ).append( gracefulShutdownRequest.getTimeOffline() ).append( '\n' );
230        sb.append( "    Delay : " ).append( gracefulShutdownRequest.getDelay() ).append( '\n' );
231
232        return sb.toString();
233    }
234}