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 *    https://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.cancel;
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.Grammar;
026import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
027import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
028import org.apache.directory.api.asn1.ber.tlv.BerValue;
029import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
030import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
031import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
032import org.apache.directory.api.i18n.I18n;
033import org.apache.directory.api.util.Strings;
034import org.slf4j.Logger;
035import org.slf4j.LoggerFactory;
036
037
038/**
039 * This class implements the Cancel operation. All the actions are declared
040 * in this class. As it is a singleton, these declaration are only done once.
041 * The grammar is :
042 * 
043 * <pre>
044 *  cancelRequestValue ::= SEQUENCE {
045 *      cancelId     MessageID 
046 *                   -- MessageID is as defined in [RFC2251]
047 * }
048 * </pre>
049 * 
050 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
051 */
052public final class CancelRequestGrammar extends AbstractGrammar<CancelRequestContainer>
053{
054    /** The logger */
055    static final Logger LOG = LoggerFactory.getLogger( CancelRequestGrammar.class );
056
057    /** The instance of grammar. CancelGrammar is a singleton */
058    private static Grammar<CancelRequestContainer> instance = new CancelRequestGrammar();
059
060
061    /**
062     * Creates a new GracefulDisconnectGrammar object.
063     */
064    @SuppressWarnings("unchecked")
065    private CancelRequestGrammar()
066    {
067        setName( CancelRequestGrammar.class.getName() );
068
069        // Create the transitions table
070        super.transitions = new GrammarTransition[CancelStatesEnum.LAST_CANCEL_STATE.ordinal()][256];
071
072        /**
073         * Transition from init state to cancel sequence
074         * cancelRequestValue ::= SEQUENCE {
075         *     ... 
076         * 
077         * Creates the Cancel object
078         */
079        super.transitions[CancelStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
080            new GrammarTransition<CancelRequestContainer>( CancelStatesEnum.START_STATE,
081                CancelStatesEnum.CANCEL_SEQUENCE_STATE,
082                UniversalTag.SEQUENCE.getValue(),
083                null );
084
085        /**
086         * Transition from cancel SEQ to cancelId
087         * 
088         * cancelRequestValue ::= SEQUENCE {
089         *     cancelId   MessageID 
090         * }
091         *     
092         * Set the cancelId value into the Cancel object.    
093         */
094        super.transitions[CancelStatesEnum.CANCEL_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER.getValue()] =
095            new GrammarTransition<CancelRequestContainer>( CancelStatesEnum.CANCEL_SEQUENCE_STATE,
096                CancelStatesEnum.CANCEL_ID_STATE,
097                UniversalTag.INTEGER.getValue(),
098                new GrammarAction<CancelRequestContainer>( "Stores CancelId" )
099                {
100                    public void action( CancelRequestContainer cancelContainer ) throws DecoderException
101                    {
102                        BerValue value = cancelContainer.getCurrentTLV().getValue();
103
104                        try
105                        {
106                            int cancelId = IntegerDecoder.parse( value, 0, Integer.MAX_VALUE );
107
108                            if ( LOG.isDebugEnabled() )
109                            {
110                                LOG.debug( I18n.msg( I18n.MSG_08200_CANCEL_ID, cancelId ) );
111                            }
112
113                            cancelContainer.getCancelRequest().setCancelId( cancelId );
114                            
115                            cancelContainer.setGrammarEndAllowed( true );
116                        }
117                        catch ( IntegerDecoderException ide )
118                        {
119                            String msg = I18n.err( I18n.ERR_08200_CANCELID_DECODING_FAILED, Strings.dumpBytes( value.getData() ) );
120                            LOG.error( msg );
121                            throw new DecoderException( msg, ide );
122                        }
123                    }
124                } );
125    }
126
127
128    /**
129     * This class is a singleton.
130     * 
131     * @return An instance on this grammar
132     */
133    public static Grammar<CancelRequestContainer> getInstance()
134    {
135        return instance;
136    }
137}