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