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   *    https://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      /** The instance of grammar. SyncRequestValueControlGrammar is a singleton */
66      private static Grammar<SyncRequestValueContainer> instance = new SyncRequestValueGrammar();
67  
68  
69      /**
70       * Creates a new SyncRequestValueControlGrammar object.
71       */
72      @SuppressWarnings("unchecked")
73      private SyncRequestValueGrammar()
74      {
75          setName( SyncRequestValueGrammar.class.getName() );
76  
77          // Create the transitions table
78          super.transitions = new GrammarTransition[SyncRequestValueStatesEnum.LAST_SYNC_REQUEST_VALUE_STATE.ordinal()][256];
79  
80          /** 
81           * Transition from initial state to SyncRequestValue sequence
82           * SyncRequestValue ::= SEQUENCE OF {
83           *     ...
84           *     
85           * Initialize the syncRequestValue object
86           */
87          super.transitions[SyncRequestValueStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
88              new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.START_STATE,
89                  SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE,
90                  UniversalTag.SEQUENCE.getValue(),
91                  null );
92  
93          /** 
94           * Transition from SyncRequestValue sequence to Change types
95           * SyncRequestValue ::= SEQUENCE OF {
96           *     mode ENUMERATED {
97           *         -- 0 unused
98           *         refreshOnly       (1),
99           *         -- 2 reserved
100          *         refreshAndPersist (3)
101          *     },
102          *     ...
103          *     
104          * Stores the mode value
105          */
106         super.transitions[SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.ENUMERATED
107             .getValue()] =
108             new GrammarTransition<SyncRequestValueContainer>(
109                 SyncRequestValueStatesEnum.SYNC_REQUEST_VALUE_SEQUENCE_STATE,
110                 SyncRequestValueStatesEnum.MODE_STATE,
111                 UniversalTag.ENUMERATED.getValue(),
112                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl mode" )
113                 {
114                     public void action( SyncRequestValueContainer container ) throws DecoderException
115                     {
116                         BerValue value = container.getCurrentTLV().getValue();
117 
118                         try
119                         {
120                             // Check that the value is into the allowed interval
121                             int mode = IntegerDecoder.parse( value,
122                                 SynchronizationModeEnum.UNUSED.getValue(),
123                                 SynchronizationModeEnum.REFRESH_AND_PERSIST.getValue() );
124 
125                             SynchronizationModeEnum modeEnum = SynchronizationModeEnum.getSyncMode( mode );
126 
127                             if ( LOG.isDebugEnabled() )
128                             {
129                                 LOG.debug( I18n.msg( I18n.MSG_08100_MODE, modeEnum ) );
130                             }
131 
132                             container.getSyncRequestValue().setMode( modeEnum );
133 
134                             // We can have an END transition
135                             container.setGrammarEndAllowed( true );
136                         }
137                         catch ( IntegerDecoderException ide )
138                         {
139                             String msg = I18n.err( I18n.ERR_08100_SYNC_REQUEST_VALUE_MODE_DECODING_FAILED );
140                             LOG.error( msg, ide );
141                             throw new DecoderException( msg, ide );
142                         }
143                     }
144                 } );
145 
146         /** 
147          * Transition from mode to cookie
148          * SyncRequestValue ::= SEQUENCE OF {
149          *     ...
150          *     cookie     syncCookie OPTIONAL,
151          *     ...
152          *     
153          * Stores the cookie
154          */
155         super.transitions[SyncRequestValueStatesEnum.MODE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
156             new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.MODE_STATE,
157                 SyncRequestValueStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING.getValue(),
158                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl cookie" )
159                 {
160                     public void action( SyncRequestValueContainer container )
161                     {
162                         BerValue value = container.getCurrentTLV().getValue();
163 
164                         byte[] cookie = value.getData();
165 
166                         if ( LOG.isDebugEnabled() )
167                         {
168                             LOG.debug( I18n.msg( I18n.MSG_08000_COOKIE, Strings.dumpBytes( cookie ) ) );
169                         }
170 
171                         container.getSyncRequestValue().setCookie( cookie );
172 
173                         // We can have an END transition
174                         container.setGrammarEndAllowed( true );
175                     }
176                 } );
177 
178         /** 
179          * Transition from mode to reloadHint
180          * SyncRequestValue ::= SEQUENCE OF {
181          *     ...
182          *     reloadHint BOOLEAN DEFAULT FALSE
183          * }
184          *     
185          * Stores the reloadHint flag
186          */
187         super.transitions[SyncRequestValueStatesEnum.MODE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
188             new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.MODE_STATE,
189                 SyncRequestValueStatesEnum.RELOAD_HINT_STATE, UniversalTag.BOOLEAN.getValue(),
190                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl reloadHint flag" )
191                 {
192                     public void action( SyncRequestValueContainer container ) throws DecoderException
193                     {
194                         BerValue value = container.getCurrentTLV().getValue();
195 
196                         try
197                         {
198                             boolean reloadHint = BooleanDecoder.parse( value );
199 
200                             if ( LOG.isDebugEnabled() )
201                             {
202                                 LOG.debug( I18n.msg( I18n.MSG_08104_RELOAD_HINT, reloadHint ) );
203                             }
204 
205                             container.getSyncRequestValue().setReloadHint( reloadHint );
206 
207                             // We can have an END transition
208                             container.setGrammarEndAllowed( true );
209                         }
210                         catch ( BooleanDecoderException bde )
211                         {
212                             String msg = I18n.err( I18n.ERR_08101_RELOAD_HINT_DECODING_FAILED );
213                             LOG.error( msg, bde );
214                             throw new DecoderException( msg, bde );
215                         }
216                     }
217                 } );
218 
219         /** 
220          * Transition from cookie to reloadHint
221          * SyncRequestValue ::= SEQUENCE OF {
222          *     ...
223          *     reloadHint BOOLEAN DEFAULT FALSE
224          * }
225          *     
226          * Stores the reloadHint flag
227          */
228         super.transitions[SyncRequestValueStatesEnum.COOKIE_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
229             new GrammarTransition<SyncRequestValueContainer>( SyncRequestValueStatesEnum.COOKIE_STATE,
230                 SyncRequestValueStatesEnum.RELOAD_HINT_STATE, UniversalTag.BOOLEAN.getValue(),
231                 new GrammarAction<SyncRequestValueContainer>( "Set SyncRequestValueControl reloadHint flag" )
232                 {
233                     public void action( SyncRequestValueContainer container ) throws DecoderException
234                     {
235                         BerValue value = container.getCurrentTLV().getValue();
236 
237                         try
238                         {
239                             boolean reloadHint = BooleanDecoder.parse( value );
240 
241                             if ( LOG.isDebugEnabled() )
242                             {
243                                 LOG.debug( I18n.msg( I18n.MSG_08104_RELOAD_HINT, reloadHint ) );
244                             }
245 
246                             container.getSyncRequestValue().setReloadHint( reloadHint );
247 
248                             // We can have an END transition
249                             container.setGrammarEndAllowed( true );
250                         }
251                         catch ( BooleanDecoderException bde )
252                         {
253                             String msg = I18n.err( I18n.ERR_08101_RELOAD_HINT_DECODING_FAILED );
254                             LOG.error( msg, bde );
255                             throw new DecoderException( msg, bde );
256                         }
257                     }
258                 } );
259     }
260 
261 
262     /**
263      * This class is a singleton.
264      * 
265      * @return An instance on this grammar
266      */
267     public static Grammar<SyncRequestValueContainer> getInstance()
268     {
269         return instance;
270     }
271 }