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