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.search.controls.persistentSearch;
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.BooleanDecoder;
033 import org.apache.directory.shared.asn1.util.BooleanDecoderException;
034 import org.apache.directory.shared.asn1.util.IntegerDecoder;
035 import org.apache.directory.shared.asn1.util.IntegerDecoderException;
036 import org.apache.directory.shared.i18n.I18n;
037 import org.slf4j.Logger;
038 import org.slf4j.LoggerFactory;
039
040
041 /**
042 * This class implements the PSearchControl. 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 * PersistenceSearch ::= SEQUENCE {
048 * changeTypes INTEGER, -- an OR combinaison of 0, 1, 2 and 4 --
049 * changeOnly BOOLEAN,
050 * returnECs BOOLEAN
051 * }
052 *
053 * The changeTypes field is the logical OR of one or more of these values:
054 * add (1),
055 * delete (2),
056 * modify (4),
057 * modDN (8).
058 *
059 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
060 * @version $Rev: 912399 $, $Date: 2010-02-21 21:52:31 +0100 (Dim, 21 fév 2010) $,
061 */
062 public class PersistentSearchControlGrammar extends AbstractGrammar
063 {
064 /** The logger */
065 static final Logger log = LoggerFactory.getLogger( PersistentSearchControlGrammar.class );
066
067 /** Speedup for logs */
068 static final boolean IS_DEBUG = log.isDebugEnabled();
069
070 /** The instance of grammar. PSearchControlGrammar is a singleton */
071 private static IGrammar instance = new PersistentSearchControlGrammar();
072
073
074 /**
075 * Creates a new PSearchControlGrammar object.
076 */
077 private PersistentSearchControlGrammar()
078 {
079 name = PersistentSearchControlGrammar.class.getName();
080 statesEnum = PersistentSearchControlStatesEnum.getInstance();
081
082 // Create the transitions table
083 super.transitions = new GrammarTransition[PersistentSearchControlStatesEnum.LAST_PSEARCH_STATE][256];
084
085 /**
086 * Transition from initial state to Psearch sequence
087 * PSearch ::= SEQUENCE OF {
088 * ...
089 *
090 * Initialize the persistence search object
091 */
092 super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] =
093 new GrammarTransition( IStates.INIT_GRAMMAR_STATE,
094 PersistentSearchControlStatesEnum.PSEARCH_SEQUENCE_STATE,
095 UniversalTag.SEQUENCE_TAG, null );
096
097
098 /**
099 * Transition from Psearch sequence to Change types
100 * PSearch ::= SEQUENCE OF {
101 * changeTypes INTEGER, -- an OR combinaison of 0, 1, 2 and 4 --
102 * ...
103 *
104 * Stores the change types value
105 */
106 super.transitions[PersistentSearchControlStatesEnum.PSEARCH_SEQUENCE_STATE][UniversalTag.INTEGER_TAG] =
107 new GrammarTransition( PersistentSearchControlStatesEnum.PSEARCH_SEQUENCE_STATE,
108 PersistentSearchControlStatesEnum.CHANGE_TYPES_STATE,
109 UniversalTag.INTEGER_TAG,
110 new GrammarAction( "Set PSearchControl changeTypes" )
111 {
112 public void action( IAsn1Container container ) throws DecoderException
113 {
114 PersistentSearchControlContainer psearchContainer = ( PersistentSearchControlContainer ) container;
115 Value value = psearchContainer.getCurrentTLV().getValue();
116
117 try
118 {
119 // Check that the value is into the allowed interval
120 int changeTypes = IntegerDecoder.parse( value,
121 PersistentSearchControl.CHANGE_TYPES_MIN,
122 PersistentSearchControl.CHANGE_TYPES_MAX );
123
124 if ( IS_DEBUG )
125 {
126 log.debug( "changeTypes = " + changeTypes );
127 }
128
129 psearchContainer.getPSearchControl().setChangeTypes( changeTypes );
130 }
131 catch ( IntegerDecoderException e )
132 {
133 String msg = I18n.err( I18n.ERR_04051 );
134 log.error( msg, e );
135 throw new DecoderException( msg );
136 }
137 }
138 } );
139
140 /**
141 * Transition from Change types to Changes only
142 * PSearch ::= SEQUENCE OF {
143 * ...
144 * changeOnly BOOLEAN,
145 * ...
146 *
147 * Stores the change only flag
148 */
149 super.transitions[PersistentSearchControlStatesEnum.CHANGE_TYPES_STATE][UniversalTag.BOOLEAN_TAG] =
150 new GrammarTransition( PersistentSearchControlStatesEnum.CHANGE_TYPES_STATE,
151 PersistentSearchControlStatesEnum.CHANGES_ONLY_STATE, UniversalTag.BOOLEAN_TAG,
152 new GrammarAction( "Set PSearchControl changesOnly" )
153 {
154 public void action( IAsn1Container container ) throws DecoderException
155 {
156 PersistentSearchControlContainer psearchContainer = ( PersistentSearchControlContainer ) container;
157 Value value = psearchContainer.getCurrentTLV().getValue();
158
159 try
160 {
161 boolean changesOnly = BooleanDecoder.parse( value );
162
163 if ( IS_DEBUG )
164 {
165 log.debug( "changesOnly = " + changesOnly );
166 }
167
168 psearchContainer.getPSearchControl().setChangesOnly( changesOnly );
169 }
170 catch ( BooleanDecoderException e )
171 {
172 String msg = I18n.err( I18n.ERR_04052 );
173 log.error( msg, e );
174 throw new DecoderException( msg );
175 }
176 }
177 } );
178
179 /**
180 * Transition from Change types to Changes only
181 * PSearch ::= SEQUENCE OF {
182 * ...
183 * returnECs BOOLEAN
184 * }
185 *
186 * Stores the return ECs flag
187 */
188 super.transitions[PersistentSearchControlStatesEnum.CHANGES_ONLY_STATE][UniversalTag.BOOLEAN_TAG] =
189 new GrammarTransition( PersistentSearchControlStatesEnum.CHANGES_ONLY_STATE,
190 PersistentSearchControlStatesEnum.RETURN_ECS_STATE, UniversalTag.BOOLEAN_TAG,
191 new GrammarAction( "Set PSearchControl returnECs" )
192 {
193 public void action( IAsn1Container container ) throws DecoderException
194 {
195 PersistentSearchControlContainer psearchContainer = ( PersistentSearchControlContainer ) container;
196 Value value = psearchContainer.getCurrentTLV().getValue();
197
198 try
199 {
200 boolean returnECs = BooleanDecoder.parse( value );
201
202 if ( IS_DEBUG )
203 {
204 log.debug( "returnECs = " + returnECs );
205 }
206
207 psearchContainer.getPSearchControl().setReturnECs( returnECs );
208
209 // We can have an END transition
210 psearchContainer.grammarEndAllowed( true );
211 }
212 catch ( BooleanDecoderException e )
213 {
214 String msg = I18n.err( I18n.ERR_04053 );
215 log.error( msg, e );
216 throw new DecoderException( msg );
217 }
218 }
219 } );
220 }
221
222
223 /**
224 * This class is a singleton.
225 *
226 * @return An instance on this grammar
227 */
228 public static IGrammar getInstance()
229 {
230 return instance;
231 }
232 }