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.extended.operations.gracefulDisconnect;
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.codec.extended.operations.GracefulActionConstants;
036 import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException;
037 import org.apache.directory.shared.ldap.util.LdapURL;
038 import org.apache.directory.shared.ldap.util.StringTools;
039 import org.slf4j.Logger;
040 import org.slf4j.LoggerFactory;
041
042
043 /**
044 * This class implements the Graceful Disconnect. All the actions are declared
045 * in this class. As it is a singleton, these declaration are only done once.
046 * The grammar is :
047 *
048 * <pre>
049 * GracefulDisconnect ::= SEQUENCE {
050 * timeOffline INTEGER (0..720) DEFAULT 0,
051 * delay [0] INTEGER (0..86400) DEFAULT 0,
052 * replicatedContexts Referral OPTIONAL
053 * }
054 *
055 * Referral ::= SEQUENCE OF LDAPURL
056 *
057 * LDAPURL ::= LDAPString -- limited to characters permitted in URLs
058 *
059 * LDAPString ::= OCTET STRING
060 * </pre>
061 *
062 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
063 * @version $Rev: 912399 $, $Date: 2010-02-21 22:52:31 +0200 (Sun, 21 Feb 2010) $,
064 */
065 public class GracefulDisconnectGrammar extends AbstractGrammar
066 {
067 /** The logger */
068 static final Logger log = LoggerFactory.getLogger( GracefulDisconnectGrammar.class );
069
070 /** Speedup for logs */
071 static final boolean IS_DEBUG = log.isDebugEnabled();
072
073 /** The instance of grammar. GracefulDisconnectnGrammar is a singleton */
074 private static IGrammar instance = new GracefulDisconnectGrammar();
075
076
077 /**
078 * The action used to store a Time Offline.
079 */
080 GrammarAction storeDelay = new GrammarAction( "Set Graceful Disconnect Delay" )
081 {
082 public void action( IAsn1Container container ) throws DecoderException
083 {
084 GracefulDisconnectContainer gracefulDisconnectContainer = ( GracefulDisconnectContainer ) container;
085 Value value = gracefulDisconnectContainer.getCurrentTLV().getValue();
086
087 try
088 {
089 int delay = IntegerDecoder.parse( value, 0, 86400 );
090
091 if ( IS_DEBUG )
092 {
093 log.debug( "Delay = " + delay );
094 }
095
096 gracefulDisconnectContainer.getGracefulDisconnect().setDelay( delay );
097 gracefulDisconnectContainer.grammarEndAllowed( true );
098 }
099 catch ( IntegerDecoderException e )
100 {
101 String msg = I18n.err( I18n.ERR_04036, StringTools.dumpBytes( value.getData() ) );
102 log.error( msg );
103 throw new DecoderException( msg );
104 }
105 }
106 };
107
108 /**
109 * The action used to store a referral.
110 */
111 GrammarAction storeReferral = new GrammarAction( "Stores a referral" )
112 {
113 public void action( IAsn1Container container ) throws DecoderException
114 {
115 GracefulDisconnectContainer gracefulDisconnectContainer = ( GracefulDisconnectContainer ) container;
116 Value value = gracefulDisconnectContainer.getCurrentTLV().getValue();
117
118 try
119 {
120 LdapURL url = new LdapURL( value.getData() );
121 gracefulDisconnectContainer.getGracefulDisconnect().addReplicatedContexts( url );
122 gracefulDisconnectContainer.grammarEndAllowed( true );
123
124 if ( IS_DEBUG )
125 {
126 log.debug( "Stores a referral : {}", url );
127 }
128 }
129 catch ( LdapURLEncodingException e )
130 {
131 String msg = "failed to decode the URL '" + StringTools.dumpBytes( value.getData() ) + "'";
132 log.error( msg );
133 throw new DecoderException( msg );
134 }
135 }
136 };
137
138 /**
139 * The action used to store a Time Offline.
140 */
141 GrammarAction storeTimeOffline = new GrammarAction( "Set Graceful Disconnect time offline" )
142 {
143 public void action( IAsn1Container container ) throws DecoderException
144 {
145 GracefulDisconnectContainer gracefulDisconnectContainer = ( GracefulDisconnectContainer ) container;
146 Value value = gracefulDisconnectContainer.getCurrentTLV().getValue();
147
148 try
149 {
150 int timeOffline = IntegerDecoder.parse( value, 0, 720 );
151
152 if ( IS_DEBUG )
153 {
154 log.debug( "Time Offline = " + timeOffline );
155 }
156
157 gracefulDisconnectContainer.getGracefulDisconnect().setTimeOffline( timeOffline );
158 gracefulDisconnectContainer.grammarEndAllowed( true );
159 }
160 catch ( IntegerDecoderException e )
161 {
162 String msg = I18n.err( I18n.ERR_04037, StringTools.dumpBytes( value.getData() ) );
163 log.error( msg );
164 throw new DecoderException( msg );
165 }
166 }
167 };
168
169 /**
170 * Creates a new GracefulDisconnectGrammar object.
171 */
172 private GracefulDisconnectGrammar()
173 {
174 name = GracefulDisconnectGrammar.class.getName();
175 statesEnum = GracefulDisconnectStatesEnum.getInstance();
176
177 // Create the transitions table
178 super.transitions = new GrammarTransition[GracefulDisconnectStatesEnum.LAST_GRACEFUL_DISCONNECT_STATE][256];
179
180 /**
181 * Transition from init state to graceful disconnect
182 * GracefulDisconnect ::= SEQUENCE {
183 * ...
184 *
185 * Creates the GracefulDisconnect object
186 */
187 super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] =
188 new GrammarTransition( IStates.INIT_GRAMMAR_STATE,
189 GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE,
190 UniversalTag.SEQUENCE_TAG,
191 new GrammarAction(
192 "Init Graceful Disconnect" )
193 {
194 public void action( IAsn1Container container )
195 {
196 GracefulDisconnectContainer gracefulDisconnectContainer = ( GracefulDisconnectContainer ) container;
197 GracefulDisconnect gracefulDisconnect = new GracefulDisconnect();
198 gracefulDisconnectContainer.setGracefulDisconnect( gracefulDisconnect );
199 gracefulDisconnectContainer.grammarEndAllowed( true );
200 }
201 } );
202
203 /**
204 * Transition from graceful disconnect to time offline
205 *
206 * GracefulDisconnect ::= SEQUENCE {
207 * timeOffline INTEGER (0..720) DEFAULT 0,
208 * ...
209 *
210 * Set the time offline value into the GracefulDisconnect object.
211 */
212 super.transitions[GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE][UniversalTag.INTEGER_TAG] =
213 new GrammarTransition( GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE,
214 GracefulDisconnectStatesEnum.TIME_OFFLINE_STATE,
215 UniversalTag.INTEGER_TAG,
216 storeTimeOffline );
217
218 /**
219 * Transition from graceful disconnect to delay
220 *
221 * GracefulDisconnect ::= SEQUENCE {
222 * ...
223 * delay [0] INTEGER (0..86400) DEFAULT 0,
224 * ...
225 *
226 * Set the delay value into the GracefulDisconnect object.
227 */
228 super.transitions[GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE]
229 [GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG] =
230 new GrammarTransition( GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE,
231 GracefulDisconnectStatesEnum.DELAY_STATE,
232 GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG,
233 storeDelay );
234
235 /**
236 * Transition from graceful disconnect to replicated Contexts
237 *
238 * GracefulDisconnect ::= SEQUENCE {
239 * ...
240 * replicatedContexts Referral OPTIONAL }
241 *
242 * Referral ::= SEQUENCE OF LDAPURL
243 *
244 * Get some replicated contexts. Nothing to do
245 */
246 super.transitions[GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE][UniversalTag.SEQUENCE_TAG] =
247 new GrammarTransition( GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE,
248 GracefulDisconnectStatesEnum.REPLICATED_CONTEXTS_STATE,
249 UniversalTag.SEQUENCE_TAG, null );
250
251 /**
252 * Transition from time offline to delay
253 *
254 * GracefulDisconnect ::= SEQUENCE {
255 * ...
256 * delay [0] INTEGER (0..86400) DEFAULT 0,
257 * ...
258 *
259 * Set the delay value into the GracefulDisconnect object.
260 */
261 super.transitions[GracefulDisconnectStatesEnum.TIME_OFFLINE_STATE][GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG] =
262 new GrammarTransition( GracefulDisconnectStatesEnum.TIME_OFFLINE_STATE,
263 GracefulDisconnectStatesEnum.DELAY_STATE,
264 GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG,
265 storeDelay );
266
267 /**
268 * Transition from time offline to replicated Contexts
269 *
270 * GracefulDisconnect ::= SEQUENCE {
271 * ...
272 * replicatedContexts Referral OPTIONAL }
273 *
274 * Referral ::= SEQUENCE OF LDAPURL
275 *
276 * Get some replicated contexts. Nothing to do
277 */
278 super.transitions[GracefulDisconnectStatesEnum.TIME_OFFLINE_STATE][UniversalTag.SEQUENCE_TAG] =
279 new GrammarTransition( GracefulDisconnectStatesEnum.TIME_OFFLINE_STATE,
280 GracefulDisconnectStatesEnum.REPLICATED_CONTEXTS_STATE,
281 UniversalTag.SEQUENCE_TAG, null );
282
283 /**
284 * Transition from delay to replicated contexts
285 *
286 * GracefulDisconnect ::= SEQUENCE {
287 * ...
288 * replicatedContexts Referral OPTIONAL }
289 *
290 * Referral ::= SEQUENCE OF LDAPURL
291 *
292 * Get some replicated contexts. Nothing to do
293 */
294 super.transitions[GracefulDisconnectStatesEnum.DELAY_STATE][UniversalTag.SEQUENCE_TAG] =
295 new GrammarTransition( GracefulDisconnectStatesEnum.DELAY_STATE,
296 GracefulDisconnectStatesEnum.REPLICATED_CONTEXTS_STATE,
297 UniversalTag.SEQUENCE_TAG, null );
298
299 /**
300 * Transition from replicated contexts to referral
301 *
302 * GracefulDisconnect ::= SEQUENCE {
303 * ...
304 * replicatedContexts Referral OPTIONAL }
305 *
306 * Referral ::= SEQUENCE OF LDAPURL
307 *
308 * Stores the referral
309 */
310 super.transitions[GracefulDisconnectStatesEnum.REPLICATED_CONTEXTS_STATE][UniversalTag.OCTET_STRING_TAG] =
311 new GrammarTransition( GracefulDisconnectStatesEnum.REPLICATED_CONTEXTS_STATE,
312 GracefulDisconnectStatesEnum.REFERRAL_STATE,
313 UniversalTag.OCTET_STRING_TAG,
314 storeReferral );
315
316 /**
317 * Transition from referral to referral
318 *
319 * GracefulDisconnect ::= SEQUENCE {
320 * ...
321 * replicatedContexts Referral OPTIONAL }
322 *
323 * Referral ::= SEQUENCE OF LDAPURL
324 *
325 * Stores the referral
326 */
327 super.transitions[GracefulDisconnectStatesEnum.REFERRAL_STATE][UniversalTag.OCTET_STRING_TAG] =
328 new GrammarTransition( GracefulDisconnectStatesEnum.REFERRAL_STATE,
329 GracefulDisconnectStatesEnum.REFERRAL_STATE,
330 UniversalTag.OCTET_STRING_TAG,
331 storeReferral );
332
333 }
334
335
336 /**
337 * This class is a singleton.
338 *
339 * @return An instance on this grammar
340 */
341 public static IGrammar getInstance()
342 {
343 return instance;
344 }
345 }