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 21:52:31 +0100 (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 }