View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.extras.controls.syncrepl_impl;
21  
22  
23  import org.apache.directory.api.asn1.DecoderException;
24  import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
25  import org.apache.directory.api.asn1.ber.grammar.Grammar;
26  import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
27  import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
28  import org.apache.directory.api.asn1.ber.tlv.BerValue;
29  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
30  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
31  import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
32  import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
33  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
34  import org.apache.directory.api.i18n.I18n;
35  import org.apache.directory.api.ldap.extras.controls.SynchronizationModeEnum;
36  import org.apache.directory.api.util.Strings;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  
41  /**
42   * This class implements the SyncRequestValueControl. All the actions are declared in
43   * this class. As it is a singleton, these declaration are only done once.
44   * 
45   * The decoded grammar is the following :
46   * 
47   * syncRequestValue ::= SEQUENCE {
48   *     mode ENUMERATED {
49   *     -- 0 unused
50   *     refreshOnly       (1),
51   *     -- 2 reserved
52   *     refreshAndPersist (3)
53   *     },
54   *     cookie     syncCookie OPTIONAL,
55   *     reloadHint BOOLEAN DEFAULT FALSE
56   * }
57   * 
58   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
59   */
60  public final class SyncRequestValueGrammar extends AbstractGrammar<SyncRequestValueContainer>
61  {
62      /** The logger */
63      static final Logger LOG = LoggerFactory.getLogger( SyncRequestValueGrammar.class );
64  
65      /** Speedup for logs */
66      static final boolean IS_DEBUG = LOG.isDebugEnabled();
67  
68      /** The instance of grammar. SyncRequestValueControlGrammar is a singleton */
69      private static Grammar<SyncRequestValueContainer> instance = new SyncRequestValueGrammar();
70  
71  
72      /**
73       * Creates a new SyncRequestValueControlGrammar object.
74       */
75      @SuppressWarnings("unchecked")
76      private SyncRequestValueGrammar()
77      {
78          setName( SyncRequestValueGrammar.class.getName() );
79  
80          // Create the transitions table
81          super.transitions = new GrammarTransition[SyncRequestValueStatesEnum.LAST_SYNC_REQUEST_VALUE_STATE.ordinal()][256];
82  
83          /** 
84           * Transition from initial state to SyncRequestValue sequence
85           * SyncRequestValue ::= SEQUENCE OF {
86           *     ...
87           *     
88           * Initialize the syncRequestValue object
89           */
90          super.transitions[SyncRequestValueStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
91              new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.START_STATE,
92                  SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE,
93                  UniversalTag.SEQUENCE.getValue(),
94                  null );
95  
96          /** 
97           * Transition from SyncRequestValue sequence to Change types
98           * SyncRequestValue ::= SEQUENCE OF {
99           *     mode ENUMERATED {
100          *         -- 0 unused
101          *         refreshOnly       (1),
102          *         -- 2 reserved
103          *         refreshAndPersist (3)
104          *     },
105          *     ...
106          *     
107          * Stores the mode value
108          */
109         super.transitions[SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.ENUMERATED
110             .getValue()] =
111             new GrammarTransition<SyncRequestValueContainer>(
112                 SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE,
113                 SyncRequestValueStatesEnum.MODE_STATE,
114                 UniversalTag.ENUMERATED.getValue(),
115                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl mode" )
116                 {
117                     public void action( SyncRequestValueContainer container ) throws DecoderException
118                     {
119                         BerValue value = container.getCurrentTLV().getValue();
120 
121                         try
122                         {
123                             // Check that the value is into the allowed interval
124                             int mode = IntegerDecoder.parse( value,
125                                 SynchronizationModeEnum.UNUSED.getValue(),
126                                 SynchronizationModeEnum.REFRESH_AND_PERSIST.getValue() );
127 
128                             SynchronizationModeEnum modeEnum = SynchronizationModeEnum.getSyncMode( mode );
129 
130                             if ( IS_DEBUG )
131                             {
132                                 LOG.debug( "Mode = " + modeEnum );
133                             }
134 
135                             container.getSyncRequestValueControl().setMode( modeEnum );
136 
137                             // We can have an END transition
138                             container.setGrammarEndAllowed( true );
139                         }
140                         catch ( IntegerDecoderException ide )
141                         {
142                             String msg = I18n.err( I18n.ERR_04028 );
143                             LOG.error( msg, ide );
144                             throw new DecoderException( msg, ide );
145                         }
146                     }
147                 } );
148 
149         /** 
150          * Transition from mode to cookie
151          * SyncRequestValue ::= SEQUENCE OF {
152          *     ...
153          *     cookie     syncCookie OPTIONAL,
154          *     ...
155          *     
156          * Stores the cookie
157          */
158         super.transitions[SyncRequestValueStatesEnum.MODE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
159             new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.MODE_STATE,
160                 SyncRequestValueStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING.getValue(),
161                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl cookie" )
162                 {
163                     public void action( SyncRequestValueContainer container ) throws DecoderException
164                     {
165                         BerValue value = container.getCurrentTLV().getValue();
166 
167                         byte[] cookie = value.getData();
168 
169                         if ( IS_DEBUG )
170                         {
171                             LOG.debug( "cookie = " + Strings.dumpBytes( cookie ) );
172                         }
173 
174                         container.getSyncRequestValueControl().setCookie( cookie );
175 
176                         // We can have an END transition
177                         container.setGrammarEndAllowed( true );
178                     }
179                 } );
180 
181         /** 
182          * Transition from mode to reloadHint
183          * SyncRequestValue ::= SEQUENCE OF {
184          *     ...
185          *     reloadHint BOOLEAN DEFAULT FALSE
186          * }
187          *     
188          * Stores the reloadHint flag
189          */
190         super.transitions[SyncRequestValueStatesEnum.MODE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
191             new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.MODE_STATE,
192                 SyncRequestValueStatesEnum.RELOAD_HINT_STATE, UniversalTag.BOOLEAN.getValue(),
193                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl reloadHint flag" )
194                 {
195                     public void action( SyncRequestValueContainer container ) throws DecoderException
196                     {
197                         BerValue value = container.getCurrentTLV().getValue();
198 
199                         try
200                         {
201                             boolean reloadHint = BooleanDecoder.parse( value );
202 
203                             if ( IS_DEBUG )
204                             {
205                                 LOG.debug( "reloadHint = " + reloadHint );
206                             }
207 
208                             container.getSyncRequestValueControl().setReloadHint( reloadHint );
209 
210                             // We can have an END transition
211                             container.setGrammarEndAllowed( true );
212                         }
213                         catch ( BooleanDecoderException bde )
214                         {
215                             String msg = I18n.err( I18n.ERR_04029 );
216                             LOG.error( msg, bde );
217                             throw new DecoderException( msg, bde );
218                         }
219                     }
220                 } );
221 
222         /** 
223          * Transition from cookie to reloadHint
224          * SyncRequestValue ::= SEQUENCE OF {
225          *     ...
226          *     reloadHint BOOLEAN DEFAULT FALSE
227          * }
228          *     
229          * Stores the reloadHint flag
230          */
231         super.transitions[SyncRequestValueStatesEnum.COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
232             new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.COOKIE_STATE,
233                 SyncRequestValueStatesEnum.RELOAD_HINT_STATE, UniversalTag.BOOLEAN.getValue(),
234                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl reloadHint flag" )
235                 {
236                     public void action( SyncRequestValueContainer container ) throws DecoderException
237                     {
238                         BerValue value = container.getCurrentTLV().getValue();
239 
240                         try
241                         {
242                             boolean reloadHint = BooleanDecoder.parse( value );
243 
244                             if ( IS_DEBUG )
245                             {
246                                 LOG.debug( "reloadHint = " + reloadHint );
247                             }
248 
249                             container.getSyncRequestValueControl().setReloadHint( reloadHint );
250 
251                             // We can have an END transition
252                             container.setGrammarEndAllowed( true );
253                         }
254                         catch ( BooleanDecoderException bde )
255                         {
256                             String msg = I18n.err( I18n.ERR_04029 );
257                             LOG.error( msg, bde );
258                             throw new DecoderException( msg, bde );
259                         }
260                     }
261                 } );
262     }
263 
264 
265     /**
266      * This class is a singleton.
267      * 
268      * @return An instance on this grammar
269      */
270     public static Grammar<SyncRequestValueContainer> getInstance()
271     {
272         return instance;
273     }
274 }