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 021package org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure; 022 023 024import org.apache.directory.api.asn1.DecoderException; 025import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar; 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.TLV; 029import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 030import org.apache.directory.api.i18n.I18n; 031import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory; 032import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureParameter; 033import org.apache.directory.api.util.Strings; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037 038/** 039 * ASN.1 BER Grammar for Stored Procedure Extended Operation 040 * 041 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 042 */ 043public final class StoredProcedureGrammar extends AbstractGrammar<StoredProcedureContainer> 044{ 045 //~ Static fields/initializers ----------------------------------------------------------------- 046 047 /** The logger */ 048 //private static final Logger log = LoggerFactory.getLogger( StoredProcedureGrammar.class ); 049 static final Logger LOG = LoggerFactory.getLogger( StoredProcedureGrammar.class ); 050 051 /** The instance of grammar. StoredProcedureGrammar is a singleton. */ 052 private static StoredProcedureGrammar instance = new StoredProcedureGrammar(); 053 054 055 //~ Constructors ------------------------------------------------------------------------------- 056 057 /** 058 * Creates a new StoredProcedureGrammar object. 059 */ 060 @SuppressWarnings("unchecked") 061 private StoredProcedureGrammar() 062 { 063 setName( StoredProcedureGrammar.class.getName() ); 064 065 // Create the transitions table 066 super.transitions = new GrammarTransition[StoredProcedureStatesEnum.LAST_STORED_PROCEDURE_STATE.ordinal()][256]; 067 068 //============================================================================================ 069 // StoredProcedure Message 070 //============================================================================================ 071 // StoredProcedure ::= SEQUENCE { 072 // ... 073 // Nothing to do. 074 super.transitions[StoredProcedureStatesEnum.START_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 075 new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.START_STATE, 076 StoredProcedureStatesEnum.STORED_PROCEDURE_STATE, 077 UniversalTag.SEQUENCE.getValue(), 078 null ); 079 080 // language OCTETSTRING, (Tag) 081 // ... 082 // 083 // Creates the storeProcedure and stores the language 084 super.transitions[StoredProcedureStatesEnum.STORED_PROCEDURE_STATE.ordinal()][UniversalTag.OCTET_STRING 085 .getValue()] = 086 new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.STORED_PROCEDURE_STATE, 087 StoredProcedureStatesEnum.LANGUAGE_STATE, 088 UniversalTag.OCTET_STRING.getValue(), 089 new GrammarAction<StoredProcedureContainer>( "Stores the language" ) 090 { 091 public void action( StoredProcedureContainer container ) throws DecoderException 092 { 093 TLV tlv = container.getCurrentTLV(); 094 095 StoredProcedureRequestDecorator storedProcedure = container.getStoredProcedure(); 096 if ( storedProcedure == null ) 097 { 098 storedProcedure = new StoredProcedureRequestDecorator( LdapApiServiceFactory.getSingleton() ); 099 container.setStoredProcedure( storedProcedure ); 100 } 101 102 // Store the value. 103 if ( tlv.getLength() == 0 ) 104 { 105 // We can't have a void language ! 106 String msg = I18n.err( I18n.ERR_04038 ); 107 LOG.error( msg ); 108 throw new DecoderException( msg ); 109 } 110 else 111 { 112 // Only this field's type is String by default 113 String language = Strings.utf8ToString( tlv.getValue().getData() ); 114 115 if ( LOG.isDebugEnabled() ) 116 { 117 LOG.debug( "SP language found: " + language ); 118 } 119 120 storedProcedure.setLanguage( language ); 121 } 122 } 123 } ); 124 125 // procedure OCTETSTRING, (Value) 126 // ... 127 // Stores the procedure. 128 super.transitions[StoredProcedureStatesEnum.LANGUAGE_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = 129 new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.LANGUAGE_STATE, 130 StoredProcedureStatesEnum.PROCEDURE_STATE, 131 UniversalTag.OCTET_STRING.getValue(), 132 new GrammarAction<StoredProcedureContainer>( "Stores the procedure" ) 133 { 134 public void action( StoredProcedureContainer container ) throws DecoderException 135 { 136 TLV tlv = container.getCurrentTLV(); 137 138 StoredProcedureRequestDecorator storedProcedure = container.getStoredProcedure(); 139 140 // Store the value. 141 if ( tlv.getLength() == 0 ) 142 { 143 // We can't have a void procedure ! 144 String msg = I18n.err( I18n.ERR_04039 ); 145 LOG.error( msg ); 146 throw new DecoderException( msg ); 147 } 148 else 149 { 150 byte[] procedure = tlv.getValue().getData(); 151 152 storedProcedure.setProcedure( procedure ); 153 } 154 155 if ( LOG.isDebugEnabled() ) 156 { 157 LOG.debug( "Procedure found : " + storedProcedure.getProcedureSpecification() ); 158 } 159 } 160 } ); 161 162 // parameters SEQUENCE OF Parameter { (Value) 163 // ... 164 // The list of parameters will be created with the first parameter. 165 // We can have an empty list of parameters, so the PDU can be empty 166 super.transitions[StoredProcedureStatesEnum.PROCEDURE_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 167 new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PROCEDURE_STATE, 168 StoredProcedureStatesEnum.PARAMETERS_STATE, 169 UniversalTag.SEQUENCE.getValue(), 170 new GrammarAction<StoredProcedureContainer>( "Stores the parameters" ) 171 { 172 public void action( StoredProcedureContainer container ) throws DecoderException 173 { 174 container.setGrammarEndAllowed( true ); 175 } 176 } ); 177 178 // parameter SEQUENCE OF { (Value) 179 // ... 180 // Nothing to do. 181 super.transitions[StoredProcedureStatesEnum.PARAMETERS_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 182 new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PARAMETERS_STATE, 183 StoredProcedureStatesEnum.PARAMETER_STATE, 184 UniversalTag.SEQUENCE.getValue(), 185 null ); 186 187 // Parameter ::= { 188 // type OCTETSTRING, (Value) 189 // ... 190 // 191 // We can create a parameter, and store its type 192 super.transitions[StoredProcedureStatesEnum.PARAMETER_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] = 193 new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PARAMETER_STATE, 194 StoredProcedureStatesEnum.PARAMETER_TYPE_STATE, 195 UniversalTag.OCTET_STRING.getValue(), 196 new GrammarAction<StoredProcedureContainer>( "Store parameter type" ) 197 { 198 public void action( StoredProcedureContainer container ) throws DecoderException 199 { 200 TLV tlv = container.getCurrentTLV(); 201 StoredProcedureRequestDecorator storedProcedure = container.getStoredProcedure(); 202 203 // Store the value. 204 if ( tlv.getLength() == 0 ) 205 { 206 // We can't have a void parameter type ! 207 String msg = I18n.err( I18n.ERR_04040 ); 208 LOG.error( msg ); 209 throw new DecoderException( msg ); 210 } 211 else 212 { 213 StoredProcedureParameter parameter = new StoredProcedureParameter(); 214 215 byte[] parameterType = tlv.getValue().getData(); 216 217 parameter.setType( parameterType ); 218 219 // We store the type in the current parameter. 220 storedProcedure.setCurrentParameter( parameter ); 221 222 if ( LOG.isDebugEnabled() ) 223 { 224 LOG.debug( "Parameter type found : " + Strings.dumpBytes( parameterType ) ); 225 } 226 227 } 228 } 229 } ); 230 231 // Parameter ::= { 232 // ... 233 // value OCTETSTRING (Tag) 234 // } 235 // Store the parameter value 236 super.transitions[StoredProcedureStatesEnum.PARAMETER_TYPE_STATE.ordinal()][UniversalTag.OCTET_STRING 237 .getValue()] = 238 new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PARAMETER_TYPE_STATE, 239 StoredProcedureStatesEnum.PARAMETER_VALUE_STATE, 240 UniversalTag.OCTET_STRING.getValue(), 241 new GrammarAction<StoredProcedureContainer>( "Store parameter value" ) 242 { 243 public void action( StoredProcedureContainer container ) throws DecoderException 244 { 245 StoredProcedureContainer storedProcedureContainer = ( StoredProcedureContainer ) container; 246 247 TLV tlv = storedProcedureContainer.getCurrentTLV(); 248 StoredProcedureRequestDecorator storedProcedure = storedProcedureContainer.getStoredProcedure(); 249 250 // Store the value. 251 if ( tlv.getLength() == 0 ) 252 { 253 // We can't have a void parameter value ! 254 String msg = I18n.err( I18n.ERR_04041 ); 255 LOG.error( msg ); 256 throw new DecoderException( msg ); 257 } 258 else 259 { 260 byte[] parameterValue = tlv.getValue().getData(); 261 262 if ( parameterValue.length != 0 ) 263 { 264 StoredProcedureParameter parameter = storedProcedure.getCurrentParameter(); 265 parameter.setValue( parameterValue ); 266 267 // We can now add a new Parameter to the procedure 268 storedProcedure.addParameter( parameter ); 269 270 if ( LOG.isDebugEnabled() ) 271 { 272 LOG.debug( "Parameter value found : " + Strings.dumpBytes( parameterValue ) ); 273 } 274 } 275 else 276 { 277 String msg = I18n.err( I18n.ERR_04042 ); 278 LOG.error( msg ); 279 throw new DecoderException( msg ); 280 } 281 } 282 283 // The only possible END state for the grammar is here 284 container.setGrammarEndAllowed( true ); 285 } 286 } ); 287 288 // Parameters ::= SEQUENCE OF Parameter 289 // 290 // Loop on next parameter 291 super.transitions[StoredProcedureStatesEnum.PARAMETER_VALUE_STATE.ordinal()][UniversalTag.SEQUENCE.getValue()] = 292 new GrammarTransition<StoredProcedureContainer>( StoredProcedureStatesEnum.PARAMETER_VALUE_STATE, 293 StoredProcedureStatesEnum.PARAMETER_STATE, 294 UniversalTag.SEQUENCE.getValue(), 295 null ); 296 } 297 298 299 //~ Methods ------------------------------------------------------------------------------------ 300 301 /** 302 * Get the instance of this grammar 303 * 304 * @return An instance on the StoredProcedure Grammar 305 */ 306 public static StoredProcedureGrammar getInstance() 307 { 308 return instance; 309 } 310}