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     */
020    package org.apache.directory.shared.ldap.codec.controls.replication.syncRequestValue;
021    
022    
023    import org.apache.directory.shared.asn1.ber.IAsn1Container;
024    import org.apache.directory.shared.asn1.ber.grammar.AbstractGrammar;
025    import org.apache.directory.shared.asn1.ber.grammar.GrammarAction;
026    import org.apache.directory.shared.asn1.ber.grammar.GrammarTransition;
027    import org.apache.directory.shared.asn1.ber.grammar.IGrammar;
028    import org.apache.directory.shared.asn1.ber.grammar.IStates;
029    import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
030    import org.apache.directory.shared.asn1.ber.tlv.Value;
031    import org.apache.directory.shared.asn1.codec.DecoderException;
032    import org.apache.directory.shared.asn1.util.BooleanDecoder;
033    import org.apache.directory.shared.asn1.util.BooleanDecoderException;
034    import org.apache.directory.shared.asn1.util.IntegerDecoder;
035    import org.apache.directory.shared.asn1.util.IntegerDecoderException;
036    import org.apache.directory.shared.i18n.I18n;
037    import org.apache.directory.shared.ldap.message.control.replication.SynchronizationModeEnum;
038    import org.apache.directory.shared.ldap.util.StringTools;
039    import org.slf4j.Logger;
040    import org.slf4j.LoggerFactory;
041    
042    
043    /**
044     * This class implements the SyncRequestValueControl. All the actions are declared in
045     * this class. As it is a singleton, these declaration are only done once.
046     * 
047     * The decoded grammar is the following :
048     * 
049     * syncRequestValue ::= SEQUENCE {
050     *     mode ENUMERATED {
051     *     -- 0 unused
052     *     refreshOnly       (1),
053     *     -- 2 reserved
054     *     refreshAndPersist (3)
055     *     },
056     *     cookie     syncCookie OPTIONAL,
057     *     reloadHint BOOLEAN DEFAULT FALSE
058     * }
059     * 
060     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
061     * @version $Rev: 741888 $, $Date: 2009-02-07 13:57:03 +0100 (Sat, 07 Feb 2009) $, 
062     */
063    public class SyncRequestValueControlGrammar extends AbstractGrammar
064    {
065        /** The logger */
066        static final Logger LOG = LoggerFactory.getLogger( SyncRequestValueControlGrammar.class );
067    
068        /** Speedup for logs */
069        static final boolean IS_DEBUG = LOG.isDebugEnabled();
070    
071        /** The instance of grammar. SyncRequestValueControlGrammar is a singleton */
072        private static IGrammar instance = new SyncRequestValueControlGrammar();
073    
074    
075        /**
076         * Creates a new SyncRequestValueControlGrammar object.
077         */
078        private SyncRequestValueControlGrammar()
079        {
080            name = SyncRequestValueControlGrammar.class.getName();
081            statesEnum = SyncRequestValueControlStatesEnum.getInstance();
082    
083            // Create the transitions table
084            super.transitions = new GrammarTransition[SyncRequestValueControlStatesEnum.LAST_SYNC_REQUEST_VALUE_STATE][256];
085    
086            /** 
087             * Transition from initial state to SyncRequestValue sequence
088             * SyncRequestValue ::= SEQUENCE OF {
089             *     ...
090             *     
091             * Initialize the syncRequestValue object
092             */
093            super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] = 
094                new GrammarTransition( IStates.INIT_GRAMMAR_STATE, 
095                                        SyncRequestValueControlStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE, 
096                                        UniversalTag.SEQUENCE_TAG, 
097                    null );
098    
099    
100            /** 
101             * Transition from SyncRequestValue sequence to Change types
102             * SyncRequestValue ::= SEQUENCE OF {
103             *     mode ENUMERATED {
104             *         -- 0 unused
105             *         refreshOnly       (1),
106             *         -- 2 reserved
107             *         refreshAndPersist (3)
108             *     },
109             *     ...
110             *     
111             * Stores the mode value
112             */
113            super.transitions[SyncRequestValueControlStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE][UniversalTag.ENUMERATED_TAG] = 
114                new GrammarTransition( SyncRequestValueControlStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE, 
115                    SyncRequestValueControlStatesEnum.MODE_STATE, 
116                    UniversalTag.ENUMERATED_TAG,
117                    new GrammarAction( "Set SyncRequestValueControl mode" )
118                {
119                    public void action( IAsn1Container container ) throws DecoderException
120                    {
121                        SyncRequestValueControlContainer SyncRequestValueContainer = ( SyncRequestValueControlContainer ) container;
122                        Value value = SyncRequestValueContainer.getCurrentTLV().getValue();
123    
124                        try
125                        {
126                            // Check that the value is into the allowed interval
127                            int mode = IntegerDecoder.parse( value, 
128                                SynchronizationModeEnum.UNUSED.getValue(), 
129                                SynchronizationModeEnum.REFRESH_AND_PERSIST.getValue() );
130                            
131                            SynchronizationModeEnum modeEnum = SynchronizationModeEnum.getSyncMode( mode );
132                            
133                            if ( IS_DEBUG )
134                            {
135                                LOG.debug( "Mode = " + modeEnum );
136                            }
137    
138                            SyncRequestValueContainer.getSyncRequestValueControl().setMode( modeEnum );
139    
140                            // We can have an END transition
141                            SyncRequestValueContainer.grammarEndAllowed( true );
142                        }
143                        catch ( IntegerDecoderException e )
144                        {
145                            String msg = I18n.err( I18n.ERR_04028 );
146                            LOG.error( msg, e );
147                            throw new DecoderException( msg );
148                        }
149                    }
150                } );
151    
152    
153            /** 
154             * Transition from mode to cookie
155             * SyncRequestValue ::= SEQUENCE OF {
156             *     ...
157             *     cookie     syncCookie OPTIONAL,
158             *     ...
159             *     
160             * Stores the cookie
161             */
162            super.transitions[SyncRequestValueControlStatesEnum.MODE_STATE][UniversalTag.OCTET_STRING_TAG] = 
163                new GrammarTransition( SyncRequestValueControlStatesEnum.MODE_STATE,
164                                        SyncRequestValueControlStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING_TAG,
165                    new GrammarAction( "Set SyncRequestValueControl cookie" )
166                {
167                    public void action( IAsn1Container container ) throws DecoderException
168                    {
169                        SyncRequestValueControlContainer SyncRequestValueContainer = ( SyncRequestValueControlContainer ) container;
170                        Value value = SyncRequestValueContainer.getCurrentTLV().getValue();
171    
172                        byte[] cookie = value.getData();
173    
174                        if ( IS_DEBUG )
175                        {
176                            LOG.debug( "cookie = " + StringTools.dumpBytes( cookie ) );
177                        }
178    
179                        SyncRequestValueContainer.getSyncRequestValueControl().setCookie( cookie );
180    
181                        // We can have an END transition
182                        SyncRequestValueContainer.grammarEndAllowed( true );
183                    }
184                } );
185    
186    
187            /** 
188             * Transition from mode to reloadHint
189             * SyncRequestValue ::= SEQUENCE OF {
190             *     ...
191             *     reloadHint BOOLEAN DEFAULT FALSE
192             * }
193             *     
194             * Stores the reloadHint flag
195             */
196            super.transitions[SyncRequestValueControlStatesEnum.MODE_STATE][UniversalTag.BOOLEAN_TAG] = 
197                new GrammarTransition( SyncRequestValueControlStatesEnum.MODE_STATE,
198                                        SyncRequestValueControlStatesEnum.RELOAD_HINT_STATE, UniversalTag.BOOLEAN_TAG,
199                    new GrammarAction( "Set SyncRequestValueControl reloadHint flag" )
200                {
201                    public void action( IAsn1Container container ) throws DecoderException
202                    {
203                        SyncRequestValueControlContainer SyncRequestValueContainer = ( SyncRequestValueControlContainer ) container;
204                        Value value = SyncRequestValueContainer.getCurrentTLV().getValue();
205    
206                        try
207                        {
208                            boolean reloadHint = BooleanDecoder.parse( value );
209    
210                            if ( IS_DEBUG )
211                            {
212                                LOG.debug( "reloadHint = " + reloadHint );
213                            }
214    
215                            SyncRequestValueContainer.getSyncRequestValueControl().setReloadHint( reloadHint );
216    
217                            // We can have an END transition
218                            SyncRequestValueContainer.grammarEndAllowed( true );
219                        }
220                        catch ( BooleanDecoderException e )
221                        {
222                            String msg = I18n.err( I18n.ERR_04029 );
223                            LOG.error( msg, e );
224                            throw new DecoderException( msg );
225                        }
226                    }
227                } );
228    
229    
230            /** 
231             * Transition from cookie to reloadHint
232             * SyncRequestValue ::= SEQUENCE OF {
233             *     ...
234             *     reloadHint BOOLEAN DEFAULT FALSE
235             * }
236             *     
237             * Stores the reloadHint flag
238             */
239            super.transitions[SyncRequestValueControlStatesEnum.COOKIE_STATE][UniversalTag.BOOLEAN_TAG] = 
240                new GrammarTransition( SyncRequestValueControlStatesEnum.COOKIE_STATE,
241                                        SyncRequestValueControlStatesEnum.RELOAD_HINT_STATE, UniversalTag.BOOLEAN_TAG,
242                    new GrammarAction( "Set SyncRequestValueControl reloadHint flag" )
243                {
244                    public void action( IAsn1Container container ) throws DecoderException
245                    {
246                        SyncRequestValueControlContainer SyncRequestValueContainer = ( SyncRequestValueControlContainer ) container;
247                        Value value = SyncRequestValueContainer.getCurrentTLV().getValue();
248    
249                        try
250                        {
251                            boolean reloadHint = BooleanDecoder.parse( value );
252    
253                            if ( IS_DEBUG )
254                            {
255                                LOG.debug( "reloadHint = " + reloadHint );
256                            }
257    
258                            SyncRequestValueContainer.getSyncRequestValueControl().setReloadHint( reloadHint );
259    
260                            // We can have an END transition
261                            SyncRequestValueContainer.grammarEndAllowed( true );
262                        }
263                        catch ( BooleanDecoderException e )
264                        {
265                            String msg = I18n.err( I18n.ERR_04029 );
266                            LOG.error( msg, e );
267                            throw new DecoderException( msg );
268                        }
269                    }
270                } );
271        }
272    
273    
274        /**
275         * This class is a singleton.
276         * 
277         * @return An instance on this grammar
278         */
279        public static IGrammar getInstance()
280        {
281            return instance;
282        }
283    }