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.controls.ad;
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.util.Strings;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035
036
037/**
038 * 
039 * Implementation of AdDirSync Response Control. All the actions are declared in
040 * this class. As it is a singleton, these declaration are only done once.
041 *
042 *  The decoded grammar is as follows :
043 *  
044 *  <pre>
045 * realReplControlValue ::= SEQUENCE {
046 *     flag                  integer
047 *     maxReturnLength       integer
048 *     cookie                OCTET STRING
049 * }
050 * </pre> 
051 *  
052 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
053 */
054public final class AdDirSyncGrammar extends AbstractGrammar<AdDirSyncContainer>
055{
056
057    /** the logger */
058    private static final Logger LOG = LoggerFactory.getLogger( AdDirSyncGrammar.class );
059
060    /** speedup for logger */
061    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
062
063    /** AdDirSyncControlGrammar singleton instance */
064    private static final AdDirSyncGrammar INSTANCE = new AdDirSyncGrammar();
065
066
067    /**
068     * 
069     * Creates a new instance of AdDirSyncControlGrammar.
070     *
071     */
072    @SuppressWarnings("unchecked")
073    private AdDirSyncGrammar()
074    {
075        setName( AdDirSyncGrammar.class.getName() );
076
077        super.transitions = new GrammarTransition[AdDirSyncStatesEnum.LAST_AD_DIR_SYNC_STATE.ordinal()][256];
078
079        /** 
080         * Transition from initial state to AdDirSync sequence
081         * AdDirSync ::= SEQUENCE {
082         *     ...
083         *     
084         * Initialize the adDirSync object
085         */
086        super.transitions[AdDirSyncStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 
087            new GrammarTransition<AdDirSyncContainer>(
088            AdDirSyncStatesEnum.START_STATE, AdDirSyncStatesEnum.AD_DIR_SYNC_SEQUENCE_STATE,
089            UniversalTag.SEQUENCE.getValue(),
090            new GrammarAction<AdDirSyncContainer>( "Initialization" )
091            {
092                public void action( AdDirSyncContainer container ) throws DecoderException
093                {
094                }
095            } );
096
097        
098        /**
099         * transition from start to flag
100         * realReplControlValue ::= SEQUENCE {
101         *     flag            integer
102         *    ....
103         * }
104         */
105        super.transitions[AdDirSyncStatesEnum.AD_DIR_SYNC_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER
106            .getValue()] =
107            new GrammarTransition<AdDirSyncContainer>( AdDirSyncStatesEnum.AD_DIR_SYNC_SEQUENCE_STATE,
108                AdDirSyncStatesEnum.FLAG_STATE, UniversalTag.INTEGER.getValue(),
109                new GrammarAction<AdDirSyncContainer>( "Set AdDirSyncControl parentFirst" )
110                {
111                    public void action( AdDirSyncContainer container ) throws DecoderException
112                    {
113                        BerValue value = container.getCurrentTLV().getValue();
114
115                        try
116                        {
117                            int flagValue = IntegerDecoder.parse( value );
118                            
119                            AdDirSyncFlag flag = AdDirSyncFlag.getFlag( flagValue );
120                            
121                            if ( flag == null )
122                            {
123                                String msg = "Error while decoding the AdDirSync flag, unknown value : " + flagValue;
124                                LOG.error( msg );
125                                throw new DecoderException( msg );
126                            }
127                            
128                            if ( IS_DEBUG )
129                            {
130                                LOG.debug( "flag = {}", flagValue );
131                            }
132                            
133                            container.getAdDirSyncControl().setFlag( flag );
134                        }
135                        catch ( IntegerDecoderException ide )
136                        {
137                            String msg = "Error while decoding the AdDirSync flag : " + ide.getMessage();
138                            LOG.error( msg, ide );
139                            throw new DecoderException( msg );
140                        }
141                    }
142                } );
143
144        
145        /**
146         * transition from flag to maxReturnLength
147         * realReplControlValue ::= SEQUENCE {
148         *     flag                    integer
149         *     maxReturnLength         integer
150         *    ....
151         * }
152         */
153        super.transitions[AdDirSyncStatesEnum.FLAG_STATE.ordinal()][UniversalTag.INTEGER
154            .getValue()] =
155            new GrammarTransition<AdDirSyncContainer>( AdDirSyncStatesEnum.FLAG_STATE,
156                AdDirSyncStatesEnum.MAX_RETURN_LENGTH_STATE, UniversalTag.INTEGER.getValue(),
157                new GrammarAction<AdDirSyncContainer>( "Set AdDirSyncControl maxReturnLength" )
158                {
159                    public void action( AdDirSyncContainer container ) throws DecoderException
160                    {
161                        BerValue value = container.getCurrentTLV().getValue();
162
163                        try
164                        {
165                            int maxReturnLength = IntegerDecoder.parse( value );
166                            
167                            if ( IS_DEBUG )
168                            {
169                                LOG.debug( "maxReturnLength = {}", maxReturnLength );
170                            }
171                            
172                            container.getAdDirSyncControl().setMaxReturnLength( maxReturnLength );
173                        }
174                        catch ( IntegerDecoderException ide )
175                        {
176                            String msg = "Error while decoding the AdDirSync maxReturnLength : " + ide.getMessage();
177                            LOG.error( msg, ide );
178                            throw new DecoderException( msg );
179                        }
180                    }
181                } );
182        
183        
184        /**
185         * transition from maxReturnLength to cookie
186         *     ...
187         *     maxReturnLength         integer
188         *     cookie                  OCTET STRING
189         * }
190         */
191        super.transitions[AdDirSyncStatesEnum.MAX_RETURN_LENGTH_STATE.ordinal()][UniversalTag.OCTET_STRING
192            .getValue()] =
193            new GrammarTransition<AdDirSyncContainer>( AdDirSyncStatesEnum.MAX_RETURN_LENGTH_STATE,
194                AdDirSyncStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING.getValue(),
195                new GrammarAction<AdDirSyncContainer>( "Set AdDirSyncControl cookie" )
196                {
197                    public void action( AdDirSyncContainer container ) throws DecoderException
198                    {
199                        BerValue value = container.getCurrentTLV().getValue();
200
201                        byte[] cookie = value.getData();
202
203                        if ( IS_DEBUG )
204                        {
205                            LOG.debug( "cookie = {}", Strings.dumpBytes( cookie ) );
206                        }
207
208                        container.getAdDirSyncControl().setCookie( cookie );
209
210                        container.setGrammarEndAllowed( true );
211                    }
212                } );
213    }
214
215
216    /**
217     * @return the singleton instance of the AdDirSyncControlGrammar
218     */
219    public static Grammar<AdDirSyncContainer> getInstance()
220    {
221        return INSTANCE;
222    }
223}