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 * https://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 */ 020package org.apache.directory.api.ldap.codec.controls.search.persistentSearch; 021 022 023import org.apache.directory.api.asn1.DecoderException; 024import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar; 025import org.apache.directory.api.asn1.ber.grammar.Grammar; 026import org.apache.directory.api.asn1.ber.grammar.GrammarAction; 027import org.apache.directory.api.asn1.ber.grammar.GrammarTransition; 028import org.apache.directory.api.asn1.ber.tlv.BerValue; 029import org.apache.directory.api.asn1.ber.tlv.BooleanDecoder; 030import org.apache.directory.api.asn1.ber.tlv.BooleanDecoderException; 031import org.apache.directory.api.asn1.ber.tlv.IntegerDecoder; 032import org.apache.directory.api.asn1.ber.tlv.IntegerDecoderException; 033import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 034import org.apache.directory.api.i18n.I18n; 035import org.apache.directory.api.ldap.model.message.controls.PersistentSearch; 036import org.slf4j.Logger; 037import 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 */ 060public final class PersistentSearchGrammar extends AbstractGrammar<PersistentSearchContainer> 061{ 062 /** The logger */ 063 static final Logger LOG = LoggerFactory.getLogger( PersistentSearchGrammar.class ); 064 065 /** The instance of grammar. PSearchControlGrammar is a singleton */ 066 private static Grammar<?> instance = new PersistentSearchGrammar(); 067 068 069 /** 070 * Creates a new PSearchControlGrammar object. 071 */ 072 @SuppressWarnings("unchecked") 073 private PersistentSearchGrammar() 074 { 075 setName( PersistentSearchGrammar.class.getName() ); 076 077 // Create the transitions table 078 super.transitions = new GrammarTransition[PersistentSearchStates.LAST_PSEARCH_STATE.ordinal()][256]; 079 080 /** 081 * Transition from initial state to Psearch sequence 082 * PSearch ::= SEQUENCE OF { 083 * ... 084 * 085 * Initialize the persistence search object 086 */ 087 super.transitions[PersistentSearchStates.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 088 new GrammarTransition<PersistentSearchContainer>( PersistentSearchStates.START_STATE, 089 PersistentSearchStates.PSEARCH_SEQUENCE_STATE, 090 UniversalTag.SEQUENCE.getValue(), null ); 091 092 /** 093 * Transition from Psearch sequence to Change types 094 * PSearch ::= SEQUENCE OF { 095 * changeTypes INTEGER, -- an OR combinaison of 0, 1, 2 and 4 -- 096 * ... 097 * 098 * Stores the change types value 099 */ 100 super.transitions[PersistentSearchStates.PSEARCH_SEQUENCE_STATE.ordinal()][UniversalTag.INTEGER.getValue()] = 101 new GrammarTransition<PersistentSearchContainer>( PersistentSearchStates.PSEARCH_SEQUENCE_STATE, 102 PersistentSearchStates.CHANGE_TYPES_STATE, 103 UniversalTag.INTEGER.getValue(), 104 new GrammarAction<PersistentSearchContainer>( "Set PSearchControl changeTypes" ) 105 { 106 public void action( PersistentSearchContainer container ) throws DecoderException 107 { 108 BerValue value = container.getCurrentTLV().getValue(); 109 110 try 111 { 112 // Check that the value is into the allowed interval 113 int changeTypes = IntegerDecoder.parse( value, 114 PersistentSearch.CHANGE_TYPES_MIN, 115 PersistentSearch.CHANGE_TYPES_MAX ); 116 117 if ( LOG.isDebugEnabled() ) 118 { 119 LOG.debug( I18n.msg( I18n.MSG_05304_CHANGE_TYPES, changeTypes ) ); 120 } 121 122 container.getPersistentSearch().setChangeTypes( changeTypes ); 123 } 124 catch ( IntegerDecoderException ide ) 125 { 126 String msg = I18n.err( I18n.ERR_05307_CHANGE_TYPES_DECODING_ERROR ); 127 LOG.error( msg, ide ); 128 throw new DecoderException( msg, ide ); 129 } 130 } 131 } ); 132 133 /** 134 * Transition from Change types to Changes only 135 * PSearch ::= SEQUENCE OF { 136 * ... 137 * changeOnly BOOLEAN, 138 * ... 139 * 140 * Stores the change only flag 141 */ 142 super.transitions[PersistentSearchStates.CHANGE_TYPES_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] = 143 new GrammarTransition<PersistentSearchContainer>( PersistentSearchStates.CHANGE_TYPES_STATE, 144 PersistentSearchStates.CHANGES_ONLY_STATE, UniversalTag.BOOLEAN.getValue(), 145 new GrammarAction<PersistentSearchContainer>( "Set PSearchControl changesOnly" ) 146 { 147 public void action( PersistentSearchContainer container ) throws DecoderException 148 { 149 BerValue value = container.getCurrentTLV().getValue(); 150 151 try 152 { 153 boolean changesOnly = BooleanDecoder.parse( value ); 154 155 if ( LOG.isDebugEnabled() ) 156 { 157 LOG.debug( I18n.msg( I18n.MSG_05305_CHANGES_ONLY, changesOnly ) ); 158 } 159 160 container.getPersistentSearch().setChangesOnly( changesOnly ); 161 } 162 catch ( BooleanDecoderException bde ) 163 { 164 String msg = I18n.err( I18n.ERR_05308_CHANGE_ONLY_DECODING_ERROR ); 165 LOG.error( msg, bde ); 166 throw new DecoderException( msg, bde ); 167 } 168 } 169 } ); 170 171 /** 172 * Transition from Change types to Changes only 173 * PSearch ::= SEQUENCE OF { 174 * ... 175 * returnECs BOOLEAN 176 * } 177 * 178 * Stores the return ECs flag 179 */ 180 super.transitions[PersistentSearchStates.CHANGES_ONLY_STATE.ordinal()][UniversalTag.BOOLEAN.getValue()] = 181 new GrammarTransition<PersistentSearchContainer>( PersistentSearchStates.CHANGES_ONLY_STATE, 182 PersistentSearchStates.RETURN_ECS_STATE, UniversalTag.BOOLEAN.getValue(), 183 new GrammarAction<PersistentSearchContainer>( "Set PSearchControl returnECs" ) 184 { 185 public void action( PersistentSearchContainer container ) throws DecoderException 186 { 187 BerValue value = container.getCurrentTLV().getValue(); 188 189 try 190 { 191 boolean returnECs = BooleanDecoder.parse( value ); 192 193 if ( LOG.isDebugEnabled() ) 194 { 195 LOG.debug( I18n.msg( I18n.MSG_05306_RETURN_ECS, returnECs ) ); 196 } 197 198 container.getPersistentSearch().setReturnECs( returnECs ); 199 200 // We can have an END transition 201 container.setGrammarEndAllowed( true ); 202 } 203 catch ( BooleanDecoderException bde ) 204 { 205 String msg = I18n.err( I18n.ERR_05309_RETURN_ECS_DECODING_ERROR ); 206 LOG.error( msg, bde ); 207 throw new DecoderException( msg, bde ); 208 } 209 } 210 } ); 211 } 212 213 214 /** 215 * This class is a singleton. 216 * 217 * @return An instance on this grammar 218 */ 219 public static Grammar<?> getInstance() 220 { 221 return instance; 222 } 223}