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