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.syncStateValue;
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.IntegerDecoder;
033 import org.apache.directory.shared.asn1.util.IntegerDecoderException;
034 import org.apache.directory.shared.i18n.I18n;
035 import org.apache.directory.shared.ldap.message.control.replication.SyncStateTypeEnum;
036 import org.apache.directory.shared.ldap.util.StringTools;
037 import org.slf4j.Logger;
038 import org.slf4j.LoggerFactory;
039
040
041 /**
042 * This class implements the SyncStateValueControl. All the actions are declared in
043 * this class. As it is a singleton, these declaration are only done once.
044 *
045 * The decoded grammar is the following :
046 *
047 * syncStateValue ::= SEQUENCE {
048 * state ENUMERATED {
049 * present (0),
050 * add (1),
051 * modify (2),
052 * delete (3)
053 * },
054 * entryUUID syncUUID,
055 * cookie syncCookie OPTIONAL
056 * }
057 *
058 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
059 * @version $Rev: 741888 $, $Date: 2009-02-07 13:57:03 +0100 (Sat, 07 Feb 2009) $,
060 */
061 public class SyncStateValueControlGrammar extends AbstractGrammar
062 {
063 /** The logger */
064 static final Logger LOG = LoggerFactory.getLogger( SyncStateValueControlGrammar.class );
065
066 /** Speedup for logs */
067 static final boolean IS_DEBUG = LOG.isDebugEnabled();
068
069 /** The instance of grammar. SyncStateValueControlGrammar is a singleton */
070 private static IGrammar instance = new SyncStateValueControlGrammar();
071
072
073 /**
074 * Creates a new SyncStateValueControlGrammar object.
075 */
076 private SyncStateValueControlGrammar()
077 {
078 name = SyncStateValueControlGrammar.class.getName();
079 statesEnum = SyncStateValueControlStatesEnum.getInstance();
080
081 // Create the transitions table
082 super.transitions = new GrammarTransition[SyncStateValueControlStatesEnum.LAST_SYNC_STATE_VALUE_STATE][256];
083
084 /**
085 * Transition from initial state to SyncStateValue sequence
086 * SyncRequestValue ::= SEQUENCE OF {
087 * ...
088 *
089 * Initialize the syncStateValue object
090 */
091 super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
092 IStates.INIT_GRAMMAR_STATE, SyncStateValueControlStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE,
093 UniversalTag.SEQUENCE_TAG, null );
094
095 /**
096 * Transition from SyncStateValue sequence to state type enum
097 * SyncRequestValue ::= SEQUENCE OF {
098 * state ENUMERATED {
099 * present (0),
100 * add (1),
101 * modify (2),
102 * delete (3)
103 * },
104 * ...
105 *
106 * Stores the sync state type value
107 */
108 super.transitions[SyncStateValueControlStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
109 SyncStateValueControlStatesEnum.SYNC_STATE_VALUE_SEQUENCE_STATE,
110 SyncStateValueControlStatesEnum.SYNC_TYPE_STATE, UniversalTag.ENUMERATED_TAG, new GrammarAction(
111 "Set SyncStateValueControl state type" )
112 {
113 public void action( IAsn1Container container ) throws DecoderException
114 {
115 SyncStateValueControlContainer syncStateValueContainer = ( SyncStateValueControlContainer ) container;
116 Value value = syncStateValueContainer.getCurrentTLV().getValue();
117
118 try
119 {
120 // Check that the value is into the allowed interval
121 int syncStateType = IntegerDecoder.parse( value, SyncStateTypeEnum.PRESENT.getValue(),
122 SyncStateTypeEnum.DELETE.getValue() );
123
124 SyncStateTypeEnum syncStateTypeEnum = SyncStateTypeEnum.getSyncStateType( syncStateType );
125
126 if ( IS_DEBUG )
127 {
128 LOG.debug( "SyncStateType = {}", syncStateTypeEnum );
129 }
130
131 syncStateValueContainer.getSyncStateValueControl().setSyncStateType( syncStateTypeEnum );
132
133 // move on to the entryUUID transistion
134 syncStateValueContainer.grammarEndAllowed( false );
135 }
136 catch ( IntegerDecoderException e )
137 {
138 String msg = I18n.err( I18n.ERR_04030 );
139 LOG.error( msg, e );
140 throw new DecoderException( msg );
141 }
142 }
143 } );
144
145 /**
146 * Transition from sync state tpe to entryUUID
147 * SyncStateValue ::= SEQUENCE OF {
148 * ...
149 * entryUUID syncUUID
150 * ...
151 *
152 * Stores the entryUUID
153 */
154 super.transitions[SyncStateValueControlStatesEnum.SYNC_TYPE_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
155 SyncStateValueControlStatesEnum.SYNC_TYPE_STATE, SyncStateValueControlStatesEnum.SYNC_UUID_STATE,
156 UniversalTag.OCTET_STRING_TAG, new GrammarAction( "Set SyncStateValueControl entryUUID" )
157 {
158 public void action( IAsn1Container container ) throws DecoderException
159 {
160 SyncStateValueControlContainer syncStateValueContainer = ( SyncStateValueControlContainer ) container;
161 Value value = syncStateValueContainer.getCurrentTLV().getValue();
162
163 byte[] entryUUID = value.getData();
164
165 if ( IS_DEBUG )
166 {
167 LOG.debug( "entryUUID = {}", StringTools.dumpBytes( entryUUID ) );
168 }
169
170 syncStateValueContainer.getSyncStateValueControl().setEntryUUID( entryUUID );
171
172 // We can have an END transition
173 syncStateValueContainer.grammarEndAllowed( true );
174 }
175 } );
176
177 /**
178 * Transition from entryUUID to cookie
179 * SyncRequestValue ::= SEQUENCE OF {
180 * ...
181 * cookie syncCookie OPTIONAL
182 * }
183 *
184 * Stores the reloadHint flag
185 */
186 super.transitions[SyncStateValueControlStatesEnum.SYNC_UUID_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
187 SyncStateValueControlStatesEnum.SYNC_UUID_STATE, SyncStateValueControlStatesEnum.COOKIE_STATE,
188 UniversalTag.OCTET_STRING_TAG, new GrammarAction( "Set SyncStateValueControl cookie value" )
189 {
190 public void action( IAsn1Container container ) throws DecoderException
191 {
192 SyncStateValueControlContainer syncStateValueContainer = ( SyncStateValueControlContainer ) container;
193 Value value = syncStateValueContainer.getCurrentTLV().getValue();
194
195 byte[] cookie = value.getData();
196
197 if ( IS_DEBUG )
198 {
199 LOG.debug( "cookie = {}", cookie );
200 }
201
202 syncStateValueContainer.getSyncStateValueControl().setCookie( cookie );
203
204 // terminal state
205 syncStateValueContainer.grammarEndAllowed( true );
206 }
207 } );
208 }
209
210
211 /**
212 * This class is a singleton.
213 *
214 * @return An instance on this grammar
215 */
216 public static IGrammar getInstance()
217 {
218 return instance;
219 }
220 }