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