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.IntegerDecoder;
30  import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
31  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
32  import org.apache.directory.api.i18n.I18n;
33  import org.apache.directory.api.ldap.extras.controls.syncrepl.syncState.SyncStateTypeEnum;
34  import org.apache.directory.api.util.Strings;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  
39  /**
40   * This class implements the SyncStateValueControl. All the actions are declared in
41   * this class. As it is a singleton, these declaration are only done once.
42   * 
43   * The decoded grammar is the following :
44   * 
45   *  syncStateValue ::= SEQUENCE {
46   *       state ENUMERATED {
47   *            present (0),
48   *            add (1),
49   *            modify (2),
50   *            delete (3)
51   *       },
52   *       entryUUID syncUUID,
53   *       cookie    syncCookie OPTIONAL
54   *  }
55   * 
56   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
57   */
58  public final class SyncStateValueGrammar extends AbstractGrammar<SyncStateValueContainer>
59  {
60      /** The logger */
61      static final Logger LOG = LoggerFactory.getLogger( SyncStateValueGrammar.class );
62  
63      /** Speedup for logs */
64      static final boolean IS_DEBUG = LOG.isDebugEnabled();
65  
66      /** The instance of grammar. SyncStateValueControlGrammar is a singleton */
67      private static Grammar<SyncStateValueContainer> instance = new SyncStateValueGrammar();
68  
69  
70      /**
71       * Creates a new SyncStateValueControlGrammar object.
72       */
73      @SuppressWarnings("unchecked")
74      private SyncStateValueGrammar()
75      {
76          setName( SyncStateValueGrammar.class.getName() );
77  
78          // Create the transitions table
79          super.transitions = new GrammarTransition[SyncStateValueStatesEnum.LAST_SYNC_STATE_VALUE_STATE.ordinal()][256];
80  
81          /** 
82           * Transition from initial state to SyncStateValue sequence
83           * SyncRequestValue ::= SEQUENCE OF {
84           *     ...
85           *     
86           * Initialize the syncStateValue object
87           */
88          super.transitions[SyncStateValueStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = new GrammarTransition<SyncStateValueContainer>(
89              SyncStateValueStatesEnum.START_STATE, SyncStateValueStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE,
90              UniversalTag.SEQUENCE.getValue(), null );
91  
92          /** 
93           * Transition from SyncStateValue sequence to state type enum
94           * SyncRequestValue ::= SEQUENCE OF {
95           *       state ENUMERATED {
96           *            present (0),
97           *            add (1),
98           *            modify (2),
99           *            delete (3)
100          *       },
101          *     ...
102          *     
103          * Stores the sync state type value
104          */
105         super.transitions[SyncStateValueStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE.ordinal()][UniversalTag.ENUMERATED
106             .getValue()] = new GrammarTransition<SyncStateValueContainer>(
107             SyncStateValueStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE,
108             SyncStateValueStatesEnum.SYNC_TYPE_STATE, UniversalTag.ENUMERATED.getValue(),
109             new GrammarAction<SyncStateValueContainer>( "Set SyncStateValueControl state type" )
110             {
111                 public void action( SyncStateValueContainer container ) throws DecoderException
112                 {
113                     BerValue value = container.getCurrentTLV().getValue();
114 
115                     try
116                     {
117                         // Check that the value is into the allowed interval
118                         int syncStateType = IntegerDecoder.parse( value, SyncStateTypeEnum.PRESENT.getValue(),
119                             SyncStateTypeEnum.MODDN.getValue() );
120 
121                         SyncStateTypeEnum syncStateTypeEnum = SyncStateTypeEnum.getSyncStateType( syncStateType );
122 
123                         if ( IS_DEBUG )
124                         {
125                             LOG.debug( "SyncStateType = {}", syncStateTypeEnum );
126                         }
127 
128                         container.getSyncStateValueControl().setSyncStateType( syncStateTypeEnum );
129 
130                         // move on to the entryUUID transition
131                         container.setGrammarEndAllowed( false );
132                     }
133                     catch ( IntegerDecoderException e )
134                     {
135                         String msg = I18n.err( I18n.ERR_04030 );
136                         LOG.error( msg, e );
137                         throw new DecoderException( msg );
138                     }
139                 }
140             } );
141 
142         /** 
143          * Transition from sync state tpe to entryUUID
144          * SyncStateValue ::= SEQUENCE OF {
145          *     ...
146          *     entryUUID     syncUUID
147          *     ...
148          *     
149          * Stores the entryUUID
150          */
151         super.transitions[SyncStateValueStatesEnum.SYNC_TYPE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition<SyncStateValueContainer>(
152             SyncStateValueStatesEnum.SYNC_TYPE_STATE, SyncStateValueStatesEnum.SYNC_UUID_STATE,
153             UniversalTag.OCTET_STRING.getValue(),
154             new GrammarAction<SyncStateValueContainer>( "Set SyncStateValueControl entryUUID" )
155             {
156                 public void action( SyncStateValueContainer container ) throws DecoderException
157                 {
158                     BerValue value = container.getCurrentTLV().getValue();
159 
160                     byte[] entryUUID = value.getData();
161 
162                     if ( IS_DEBUG )
163                     {
164                         LOG.debug( "entryUUID = {}", Strings.dumpBytes( entryUUID ) );
165                     }
166 
167                     container.getSyncStateValueControl().setEntryUUID( entryUUID );
168 
169                     // We can have an END transition
170                     container.setGrammarEndAllowed( true );
171                 }
172             } );
173 
174         /** 
175          * Transition from entryUUID to cookie
176          * SyncRequestValue ::= SEQUENCE OF {
177          *     ...
178          *     cookie    syncCookie OPTIONAL
179          * }
180          *     
181          * Stores the reloadHint flag
182          */
183         super.transitions[SyncStateValueStatesEnum.SYNC_UUID_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = new GrammarTransition<SyncStateValueContainer>(
184             SyncStateValueStatesEnum.SYNC_UUID_STATE, SyncStateValueStatesEnum.COOKIE_STATE,
185             UniversalTag.OCTET_STRING.getValue(),
186             new GrammarAction<SyncStateValueContainer>( "Set SyncStateValueControl cookie value" )
187             {
188                 public void action( SyncStateValueContainer container ) throws DecoderException
189                 {
190                     BerValue value = container.getCurrentTLV().getValue();
191 
192                     byte[] cookie = value.getData();
193 
194                     if ( IS_DEBUG )
195                     {
196                         LOG.debug( "cookie = {}", cookie );
197                     }
198 
199                     container.getSyncStateValueControl().setCookie( cookie );
200 
201                     // terminal state
202                     container.setGrammarEndAllowed( true );
203                 }
204             } );
205     }
206 
207 
208     /**
209      * This class is a singleton.
210      * 
211      * @return An instance on this grammar
212      */
213     public static Grammar<SyncStateValueContainer> getInstance()
214     {
215         return instance;
216     }
217 }