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 (Sun, 21 Feb 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 }