View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.codec.controls.search.persistentSearch;
21  
22  
23  import org.apache.directory.api.asn1.DecoderException;
24  import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
25  import org.apache.directory.api.asn1.ber.grammar.Grammar;
26  import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
27  import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
28  import org.apache.directory.api.asn1.ber.tlv.BerValue;
29  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder;
30  import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException;
31  import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder;
32  import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException;
33  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
34  import org.apache.directory.api.i18n.I18n;
35  import org.apache.directory.api.ldap.model.message.controls.PersistentSearch;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  
40  /**
41   * This class implements the PSearchControl. All the actions are declared in
42   * this class. As it is a singleton, these declaration are only done once.
43   * 
44   * The decoded grammar is the following :
45   * 
46   * PersistenceSearch ::= SEQUENCE {
47   *     changeTypes  INTEGER,  -- an OR combinaison of 0, 1, 2 and 4 --
48   *     changeOnly   BOOLEAN,
49   *     returnECs    BOOLEAN
50   * }
51   * 
52   * The changeTypes field is the logical OR of one or more of these values:
53   * add    (1), 
54   * delete (2), 
55   * modify (4), 
56   * modDN  (8).
57   * 
58   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
59   */
60  public final class PersistentSearchGrammar extends AbstractGrammar<PersistentSearchContainer>
61  {
62      /** The logger */
63      static final Logger LOG = LoggerFactory.getLogger( PersistentSearchGrammar.class );
64  
65      /** Speedup for logs */
66      static final boolean IS_DEBUG = LOG.isDebugEnabled();
67  
68      /** The instance of grammar. PSearchControlGrammar is a singleton */
69      private static Grammar<?> instance = new PersistentSearchGrammar();
70  
71  
72      /**
73       * Creates a new PSearchControlGrammar object.
74       */
75      @SuppressWarnings("unchecked")
76      private PersistentSearchGrammar()
77      {
78          setName( PersistentSearchGrammar.class.getName() );
79  
80          // Create the transitions table
81          super.transitions = new GrammarTransition[PersistentSearchStates.LAST_PSEARCH_STATE.ordinal()][256];
82  
83          /** 
84           * Transition from initial state to Psearch sequence
85           * PSearch ::= SEQUENCE OF {
86           *     ...
87           *     
88           * Initialize the persistence search object
89           */
90          super.transitions[PersistentSearchStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] =
91              new GrammarTransition<PersistentSearchContainer>( PersistentSearchStates.START_STATE,
92                  PersistentSearchStates.PSEARCH_SEQUENCE_STATE,
93                  UniversalTag.SEQUENCE.getValue(), null );
94  
95          /** 
96           * Transition from Psearch sequence to Change types
97           * PSearch ::= SEQUENCE OF {
98           *     changeTypes  INTEGER,  -- an OR combinaison of 0, 1, 2 and 4 --
99           *     ...
100          *     
101          * Stores the change types value
102          */
103         super.transitions[PersistentSearchStates.PSEARCH_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER.getValue()] =
104             new GrammarTransition<PersistentSearchContainer>( PersistentSearchStates.PSEARCH_SEQUENCE_STATE,
105                 PersistentSearchStates.CHANGE_TYPES_STATE,
106                 UniversalTag.INTEGER.getValue(),
107                 new GrammarAction<PersistentSearchContainer>( "Set PSearchControl changeTypes" )
108                 {
109                     public void action( PersistentSearchContainer container ) throws DecoderException
110                     {
111                         BerValue value = container.getCurrentTLV().getValue();
112 
113                         try
114                         {
115                             // Check that the value is into the allowed interval
116                             int changeTypes = IntegerDecoder.parse( value,
117                                 PersistentSearch.CHANGE_TYPES_MIN,
118                                 PersistentSearch.CHANGE_TYPES_MAX );
119 
120                             if ( IS_DEBUG )
121                             {
122                                 LOG.debug( "changeTypes = " + changeTypes );
123                             }
124 
125                             container.getPersistentSearchDecorator().setChangeTypes( changeTypes );
126                         }
127                         catch ( IntegerDecoderException e )
128                         {
129                             String msg = I18n.err( I18n.ERR_04051 );
130                             LOG.error( msg, e );
131                             throw new DecoderException( msg );
132                         }
133                     }
134                 } );
135 
136         /** 
137          * Transition from Change types to Changes only
138          * PSearch ::= SEQUENCE OF {
139          *     ...
140          *     changeOnly   BOOLEAN,
141          *     ...
142          *     
143          * Stores the change only flag
144          */
145         super.transitions[PersistentSearchStates.CHANGE_TYPES_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
146             new GrammarTransition<PersistentSearchContainer>( PersistentSearchStates.CHANGE_TYPES_STATE,
147                 PersistentSearchStates.CHANGES_ONLY_STATE, UniversalTag.BOOLEAN.getValue(),
148                 new GrammarAction<PersistentSearchContainer>( "Set PSearchControl changesOnly" )
149                 {
150                     public void action( PersistentSearchContainer container ) throws DecoderException
151                     {
152                         BerValue value = container.getCurrentTLV().getValue();
153 
154                         try
155                         {
156                             boolean changesOnly = BooleanDecoder.parse( value );
157 
158                             if ( IS_DEBUG )
159                             {
160                                 LOG.debug( "changesOnly = " + changesOnly );
161                             }
162 
163                             container.getPersistentSearchDecorator().setChangesOnly( changesOnly );
164                         }
165                         catch ( BooleanDecoderException e )
166                         {
167                             String msg = I18n.err( I18n.ERR_04052 );
168                             LOG.error( msg, e );
169                             throw new DecoderException( msg );
170                         }
171                     }
172                 } );
173 
174         /** 
175          * Transition from Change types to Changes only
176          * PSearch ::= SEQUENCE OF {
177          *     ...
178          *     returnECs    BOOLEAN 
179          * }
180          *     
181          * Stores the return ECs flag 
182          */
183         super.transitions[PersistentSearchStates.CHANGES_ONLY_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] =
184             new GrammarTransition<PersistentSearchContainer>( PersistentSearchStates.CHANGES_ONLY_STATE,
185                 PersistentSearchStates.RETURN_ECS_STATE, UniversalTag.BOOLEAN.getValue(),
186                 new GrammarAction<PersistentSearchContainer>( "Set PSearchControl returnECs" )
187                 {
188                     public void action( PersistentSearchContainer container ) throws DecoderException
189                     {
190                         BerValue value = container.getCurrentTLV().getValue();
191 
192                         try
193                         {
194                             boolean returnECs = BooleanDecoder.parse( value );
195 
196                             if ( IS_DEBUG )
197                             {
198                                 LOG.debug( "returnECs = " + returnECs );
199                             }
200 
201                             container.getPersistentSearchDecorator().setReturnECs( returnECs );
202 
203                             // We can have an END transition
204                             container.setGrammarEndAllowed( true );
205                         }
206                         catch ( BooleanDecoderException e )
207                         {
208                             String msg = I18n.err( I18n.ERR_04053 );
209                             LOG.error( msg, e );
210                             throw new DecoderException( msg );
211                         }
212                     }
213                 } );
214     }
215 
216 
217     /**
218      * This class is a singleton.
219      * 
220      * @return An instance on this grammar
221      */
222     public static Grammar<?> getInstance()
223     {
224         return instance;
225     }
226 }