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 */ 020package org.apache.directory.api.ldap.extras.extended.ads_impl.storedProcedure; 021 022 023import java.nio.BufferOverflowException; 024import java.nio.ByteBuffer; 025import java.util.LinkedList; 026import java.util.List; 027 028import org.apache.directory.api.asn1.EncoderException; 029import org.apache.directory.api.asn1.ber.tlv.BerValue; 030import org.apache.directory.api.asn1.ber.tlv.TLV; 031import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 032import org.apache.directory.api.i18n.I18n; 033import org.apache.directory.api.ldap.codec.api.ExtendedRequestDecorator; 034import org.apache.directory.api.ldap.codec.api.LdapApiService; 035import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureParameter; 036import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequest; 037import org.apache.directory.api.ldap.extras.extended.storedProcedure.StoredProcedureRequestImpl; 038import org.apache.directory.api.util.Strings; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042 043/** 044 * A Decorator for stored procedure extended operation requests. 045 * 046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 047 */ 048public class StoredProcedureRequestDecorator extends ExtendedRequestDecorator<StoredProcedureRequest> 049 implements StoredProcedureRequest 050{ 051 private static final Logger LOG = LoggerFactory.getLogger( StoredProcedureRequestDecorator.class ); 052 053 private StoredProcedureParameter currentParameter; 054 055 /** The stored procedure length */ 056 private int storedProcedureLength; 057 058 /** The parameters length */ 059 private int parametersLength; 060 061 /** The list of all parameter lengths */ 062 private List<Integer> parameterLength; 063 064 065 /** 066 * Create a new StoredProcedureRequestDecorator instance 067 * @param codec The LDAP API service to use 068 */ 069 public StoredProcedureRequestDecorator( LdapApiService codec ) 070 { 071 super( codec, new StoredProcedureRequestImpl() ); 072 } 073 074 075 /** 076 * Create a new StoredProcedureRequestDecorator instance 077 * @param codec The LDAP API service to use 078 * @param decoratedRequest The decorated request 079 */ 080 public StoredProcedureRequestDecorator( LdapApiService codec, StoredProcedureRequest decoratedRequest ) 081 { 082 super( codec, decoratedRequest ); 083 if ( decoratedRequest == null ) 084 { 085 throw new NullPointerException( "decorated stored procedulre request is null" ); 086 } 087 } 088 089 090 /** 091 * @return The current parameter 092 */ 093 public StoredProcedureParameter getCurrentParameter() 094 { 095 return currentParameter; 096 } 097 098 099 /** 100 * Sets the current parameter 101 * 102 * @param currentParameter The current parameter 103 */ 104 public void setCurrentParameter( StoredProcedureParameter currentParameter ) 105 { 106 this.currentParameter = currentParameter; 107 } 108 109 110 /** 111 * Compute the StoredProcedure length 112 * <pre> 113 * 0x30 L1 114 * | 115 * +--> 0x04 L2 language 116 * +--> 0x04 L3 procedure 117 * [+--> 0x30 L4 (parameters) 118 * | 119 * +--> 0x30 L5-1 (parameter) 120 * | | 121 * | +--> 0x04 L6-1 type 122 * | +--> 0x04 L7-1 value 123 * | 124 * +--> 0x30 L5-2 (parameter) 125 * | | 126 * | +--> 0x04 L6-2 type 127 * | +--> 0x04 L7-2 value 128 * | 129 * +--> ... 130 * | 131 * +--> 0x30 L5-m (parameter) 132 * | 133 * +--> 0x04 L6-m type 134 * +--> 0x04 L7-m value 135 * </pre> 136 */ 137 /* no qualifier */ int computeLengthInternal() 138 { 139 // The language 140 byte[] languageBytes = Strings.getBytesUtf8( getDecorated().getLanguage() ); 141 142 int languageLength = 1 + TLV.getNbBytes( languageBytes.length ) 143 + languageBytes.length; 144 145 byte[] procedure = getDecorated().getProcedure(); 146 147 // The procedure 148 int procedureLength = 1 + TLV.getNbBytes( procedure.length ) 149 + procedure.length; 150 151 // Compute parameters length value 152 if ( getDecorated().getParameters() != null ) 153 { 154 parameterLength = new LinkedList<>(); 155 156 for ( StoredProcedureParameter spParam : getDecorated().getParameters() ) 157 { 158 int localParameterLength; 159 int localParamTypeLength; 160 int localParamValueLength; 161 162 localParamTypeLength = 1 + TLV.getNbBytes( spParam.getType().length ) + spParam.getType().length; 163 localParamValueLength = 1 + TLV.getNbBytes( spParam.getValue().length ) + spParam.getValue().length; 164 165 localParameterLength = localParamTypeLength + localParamValueLength; 166 167 parametersLength += 1 + TLV.getNbBytes( localParameterLength ) + localParameterLength; 168 169 parameterLength.add( localParameterLength ); 170 } 171 } 172 173 int localParametersLength = 1 + TLV.getNbBytes( parametersLength ) + parametersLength; 174 storedProcedureLength = languageLength + procedureLength + localParametersLength; 175 176 return 1 + TLV.getNbBytes( storedProcedureLength ) + storedProcedureLength; 177 } 178 179 180 /** 181 * Encodes the StoredProcedure extended operation. 182 * 183 * @return A ByteBuffer that contains the encoded PDU 184 * @throws org.apache.directory.api.asn1.EncoderException If anything goes wrong. 185 */ 186 /* no qualifier */ ByteBuffer encodeInternal() throws EncoderException 187 { 188 // Allocate the bytes buffer. 189 ByteBuffer bb = ByteBuffer.allocate( computeLengthInternal() ); 190 191 try 192 { 193 // The StoredProcedure Tag 194 bb.put( UniversalTag.SEQUENCE.getValue() ); 195 bb.put( TLV.getBytes( storedProcedureLength ) ); 196 197 // The language 198 BerValue.encode( bb, getDecorated().getLanguage() ); 199 200 // The procedure 201 BerValue.encode( bb, getDecorated().getProcedure() ); 202 203 // The parameters sequence 204 bb.put( UniversalTag.SEQUENCE.getValue() ); 205 bb.put( TLV.getBytes( parametersLength ) ); 206 207 // The parameters list 208 if ( ( getDecorated().getParameters() != null ) && ( !getDecorated().getParameters().isEmpty() ) ) 209 { 210 int parameterNumber = 0; 211 212 for ( StoredProcedureParameter spParam : getDecorated().getParameters() ) 213 { 214 // The parameter sequence 215 bb.put( UniversalTag.SEQUENCE.getValue() ); 216 int localParameterLength = parameterLength.get( parameterNumber ); 217 bb.put( TLV.getBytes( localParameterLength ) ); 218 219 // The parameter type 220 BerValue.encode( bb, spParam.getType() ); 221 222 // The parameter value 223 BerValue.encode( bb, spParam.getValue() ); 224 225 // Go to the next parameter 226 parameterNumber++; 227 } 228 } 229 } 230 catch ( BufferOverflowException boe ) 231 { 232 throw new EncoderException( I18n.err( I18n.ERR_04005 ), boe ); 233 } 234 235 return bb; 236 } 237 238 239 /** 240 * Returns the StoredProcedure string 241 * 242 * @return The StoredProcedure string 243 */ 244 @Override 245 public String toString() 246 { 247 StringBuilder sb = new StringBuilder(); 248 249 sb.append( " StoredProcedure\n" ); 250 sb.append( " Language : '" ).append( getDecorated().getLanguage() ).append( "'\n" ); 251 sb.append( " Procedure\n" ).append( getDecorated().getProcedureSpecification() ).append( "'\n" ); 252 253 if ( ( getDecorated().getParameters() == null ) || ( !getDecorated().getParameters().isEmpty() ) ) 254 { 255 sb.append( " No parameters\n" ); 256 } 257 else 258 { 259 sb.append( " Parameters\n" ); 260 261 int i = 1; 262 263 for ( StoredProcedureParameter spParam : getDecorated().getParameters() ) 264 { 265 sb.append( " type[" ).append( i ).append( "] : '" ). 266 append( Strings.utf8ToString( spParam.getType() ) ).append( "'\n" ); 267 sb.append( " value[" ).append( i ).append( "] : '" ). 268 append( Strings.dumpBytes( spParam.getValue() ) ).append( "'\n" ); 269 } 270 } 271 272 return sb.toString(); 273 } 274 275 276 @Override 277 public void setProcedure( byte[] procedure ) 278 { 279 getDecorated().setProcedure( procedure ); 280 } 281 282 283 /** 284 * {@inheritDoc} 285 */ 286 @Override 287 public void setRequestValue( byte[] payload ) 288 { 289 StoredProcedureDecoder decoder = new StoredProcedureDecoder(); 290 StoredProcedureContainer container = new StoredProcedureContainer(); 291 292 container.setStoredProcedure( this ); 293 294 try 295 { 296 decoder.decode( ByteBuffer.wrap( payload ), container ); 297 } 298 catch ( Exception e ) 299 { 300 LOG.error( I18n.err( I18n.ERR_04165 ), e ); 301 throw new RuntimeException( e ); 302 } 303 } 304 305 306 /** 307 * {@inheritDoc} 308 */ 309 @Override 310 public byte[] getRequestValue() 311 { 312 if ( requestValue == null ) 313 { 314 try 315 { 316 requestValue = encodeInternal().array(); 317 } 318 catch ( EncoderException e ) 319 { 320 LOG.error( I18n.err( I18n.ERR_04174 ), e ); 321 throw new RuntimeException( e ); 322 } 323 } 324 325 return requestValue; 326 } 327 328 329 /** 330 * {@inheritDoc} 331 */ 332 @Override 333 public String getLanguage() 334 { 335 return getDecorated().getLanguage(); 336 } 337 338 339 /** 340 * {@inheritDoc} 341 */ 342 @Override 343 public void setLanguage( String language ) 344 { 345 getDecorated().setLanguage( language ); 346 } 347 348 349 /** 350 * {@inheritDoc} 351 */ 352 @Override 353 public String getProcedureSpecification() 354 { 355 return getDecorated().getProcedureSpecification(); 356 } 357 358 359 /** 360 * {@inheritDoc} 361 */ 362 @Override 363 public int size() 364 { 365 return getDecorated().size(); 366 } 367 368 369 /** 370 * {@inheritDoc} 371 */ 372 @Override 373 public Object getParameterType( int index ) 374 { 375 return getDecorated().getParameterType( index ); 376 } 377 378 379 /** 380 * {@inheritDoc} 381 */ 382 383 @Override 384 public Class<?> getJavaParameterType( int index ) 385 { 386 return getDecorated().getJavaParameterType( index ); 387 } 388 389 390 /** 391 * {@inheritDoc} 392 */ 393 394 @Override 395 public Object getParameterValue( int index ) 396 { 397 return getDecorated().getParameterValue( index ); 398 } 399 400 401 /** 402 * {@inheritDoc} 403 */ 404 @Override 405 public Object getJavaParameterValue( int index ) 406 { 407 return getDecorated().getJavaParameterValue( index ); 408 } 409 410 411 /** 412 * {@inheritDoc} 413 */ 414 @Override 415 public void addParameter( Object type, Object value ) 416 { 417 getDecorated().addParameter( type, value ); 418 } 419 420 421 /** 422 * {@inheritDoc} 423 */ 424 @Override 425 public byte[] getProcedure() 426 { 427 return getDecorated().getProcedure(); 428 } 429 430 431 /** 432 * {@inheritDoc} 433 */ 434 @Override 435 public List<StoredProcedureParameter> getParameters() 436 { 437 return getDecorated().getParameters(); 438 } 439 440 441 /** 442 * {@inheritDoc} 443 */ 444 @Override 445 public void addParameter( StoredProcedureParameter parameter ) 446 { 447 getDecorated().addParameter( parameter ); 448 } 449}