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 org.apache.directory.api.asn1.DecoderException;
024import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
025import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
026import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
027import org.apache.directory.api.asn1.ber.tlv.BerValue;
028import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
029import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
030import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
031import org.apache.directory.api.i18n.I18n;
032import org.apache.directory.api.ldap.extras.extended.ads_impl.gracefulDisconnect.GracefulActionConstants;
033import org.apache.directory.api.util.Strings;
034import org.slf4j.Logger;
035import org.slf4j.LoggerFactory;
036
037
038/**
039 * This class implements the Graceful shutdown. All the actions are declared in
040 * this class. As it is a singleton, these declaration are only done once. The
041 * grammar is :
042 * 
043 * <pre>
044 *  GracefulShutdwon ::= SEQUENCE {
045 *      timeOffline INTEGER (0..720) DEFAULT 0,
046 *      delay [0] INTEGER (0..86400) DEFAULT 0
047 *  }
048 * </pre>
049 * 
050 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
051 */
052public final class GracefulShutdownRequestGrammar extends AbstractGrammar<GracefulShutdownRequestContainer>
053{
054    /** The logger */
055    static final Logger LOG = LoggerFactory.getLogger( GracefulShutdownRequestGrammar.class );
056
057    /** The instance of grammar. GracefulShutdownGrammar is a singleton */
058    private static GracefulShutdownRequestGrammar instance = new GracefulShutdownRequestGrammar();
059
060
061    /**
062     * Creates a new GracefulShutdownGrammar object.
063     */
064    @SuppressWarnings("unchecked")
065    private GracefulShutdownRequestGrammar()
066    {
067        setName( GracefulShutdownRequestGrammar.class.getName() );
068
069        // Create the transitions table
070        super.transitions = new GrammarTransition[GracefulShutdownStatesEnum.LAST_GRACEFUL_SHUTDOWN_STATE.ordinal()][256];
071
072        /**
073         * Transition from init state to graceful shutdown
074         * 
075         * GracefulShutdown ::= SEQUENCE {
076         *     ...
077         *     
078         * Creates the GracefulShutdown object
079         */
080        super.transitions[GracefulShutdownStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
081            new GrammarTransition<GracefulShutdownRequestContainer>( GracefulShutdownStatesEnum.START_STATE,
082                GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE,
083                UniversalTag.SEQUENCE.getValue(),
084                new GrammarAction<GracefulShutdownRequestContainer>( "Init Graceful Shutdown" )
085                {
086                    public void action( GracefulShutdownRequestContainer container ) throws DecoderException
087                    {
088                        // We may have nothing left
089                        if ( container.getCurrentTLV().getLength() == 0 )
090                        {
091                            container.setGrammarEndAllowed( true );
092                        }
093                    }
094                } );
095
096        /**
097         * Transition from graceful shutdown to time offline
098         *
099         * GracefulShutdown ::= SEQUENCE { 
100         *     timeOffline INTEGER (0..720) DEFAULT 0,
101         *     ...
102         *     
103         * Set the time offline value into the GracefulShutdown
104         * object.
105         */
106        super.transitions[GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER
107            .getValue()] =
108            new GrammarTransition<GracefulShutdownRequestContainer>(
109                GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE,
110                GracefulShutdownStatesEnum.TIME_OFFLINE_STATE,
111                UniversalTag.INTEGER.getValue(),
112                new GrammarAction<GracefulShutdownRequestContainer>( "Set Graceful Shutdown time offline" )
113                {
114                    public void action( GracefulShutdownRequestContainer container ) throws DecoderException
115                    {
116                        BerValue value = container.getCurrentTLV().getValue();
117
118                        try
119                        {
120                            int timeOffline = IntegerDecoder.parse( value, 0, 720 );
121
122                            if ( LOG.isDebugEnabled() )
123                            {
124                                LOG.debug( I18n.msg( I18n.MSG_08216_TIME_OFFLINE, timeOffline ) );
125                            }
126
127                            container.getGracefulShutdownRequest().setTimeOffline( timeOffline );
128                            container.setGrammarEndAllowed( true );
129                        }
130                        catch ( IntegerDecoderException ide )
131                        {
132                            String msg = I18n.err( I18n.ERR_08206_TIME_OFFLINE_DECODING_FAILED, Strings.dumpBytes( value.getData() ) );
133                            LOG.error( msg );
134                            throw new DecoderException( msg, ide );
135                        }
136                    }
137                } );
138
139        /**
140         * Transition from time offline to delay
141         * 
142         * GracefulShutdown ::= SEQUENCE { 
143         *     ... 
144         *     delay [0] INTEGER (0..86400) DEFAULT 0 }
145         * 
146         * Set the delay value into the GracefulShutdown
147         * object.
148         */
149        super.transitions[GracefulShutdownStatesEnum.TIME_OFFLINE_STATE.ordinal()][GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG] =
150            new GrammarTransition<GracefulShutdownRequestContainer>( GracefulShutdownStatesEnum.TIME_OFFLINE_STATE,
151                GracefulShutdownStatesEnum.DELAY_STATE,
152                GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG,
153
154                new GrammarAction<GracefulShutdownRequestContainer>( "Set Graceful Shutdown Delay" )
155                {
156                    public void action( GracefulShutdownRequestContainer container ) throws DecoderException
157                    {
158                        BerValue value = container.getCurrentTLV().getValue();
159
160                        try
161                        {
162                            int delay = IntegerDecoder.parse( value, 0, 86400 );
163
164                            if ( LOG.isDebugEnabled() )
165                            {
166                                LOG.debug( I18n.msg( I18n.MSG_08204_DELAY, delay ) );
167                            }
168
169                            container.getGracefulShutdownRequest().setDelay( delay );
170                            container.setGrammarEndAllowed( true );
171                        }
172                        catch ( IntegerDecoderException ide )
173                        {
174                            String msg = I18n.err( I18n.ERR_08205_CANNOT_DECODE_DELAY, Strings.dumpBytes( value.getData() ) );
175                            LOG.error( msg );
176                            throw new DecoderException( msg, ide );
177                        }
178                    }
179                } );
180
181        /**
182         * Transition from graceful shutdown to delay
183         * 
184         * GracefulShutdown ::= SEQUENCE { 
185         *     ... 
186         *     delay [0] INTEGER (0..86400) DEFAULT 0 }
187         * 
188         * Set the delay value into the GracefulShutdown
189         * object.
190         */
191        super.transitions[GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE.ordinal()][GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG] =
192            new GrammarTransition<GracefulShutdownRequestContainer>(
193                GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE,
194                GracefulShutdownStatesEnum.DELAY_STATE,
195                GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG,
196
197                new GrammarAction<GracefulShutdownRequestContainer>( "Set Graceful Shutdown Delay" )
198                {
199                    public void action( GracefulShutdownRequestContainer container ) throws DecoderException
200                    {
201                        GracefulShutdownRequestContainer gracefulShutdownContainer = container;
202                        BerValue value = gracefulShutdownContainer.getCurrentTLV().getValue();
203
204                        try
205                        {
206                            int delay = IntegerDecoder.parse( value, 0, 86400 );
207
208                            if ( LOG.isDebugEnabled() )
209                            {
210                                LOG.debug( I18n.msg( I18n.MSG_08204_DELAY, delay ) );
211                            }
212
213                            gracefulShutdownContainer.getGracefulShutdownRequest().setDelay( delay );
214                            gracefulShutdownContainer.setGrammarEndAllowed( true );
215                        }
216                        catch ( IntegerDecoderException ide )
217                        {
218                            String msg = I18n.err( I18n.ERR_08205_CANNOT_DECODE_DELAY, Strings.dumpBytes( value.getData() ) );
219                            LOG.error( msg );
220                            throw new DecoderException( msg, ide );
221                        }
222                    }
223                } );
224    }
225
226
227    /**
228     * This class is a singleton.
229     * 
230     * @return An instance on this grammar
231     */
232    public static GracefulShutdownRequestGrammar getInstance()
233    {
234        return instance;
235    }
236}