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; 021 022 023 import java.io.IOException; 024 import java.io.OutputStream; 025 import java.nio.ByteBuffer; 026 import java.nio.channels.Channels; 027 import java.nio.channels.WritableByteChannel; 028 029 import org.apache.directory.shared.asn1.codec.EncoderException; 030 import org.apache.directory.shared.asn1.codec.stateful.EncoderCallback; 031 import org.apache.directory.shared.asn1.codec.stateful.EncoderMonitor; 032 import org.apache.directory.shared.asn1.codec.stateful.StatefulEncoder; 033 import org.apache.directory.shared.i18n.I18n; 034 import org.apache.directory.shared.ldap.codec.add.AddRequestCodec; 035 import org.apache.directory.shared.ldap.message.spi.Provider; 036 import org.apache.directory.shared.ldap.message.spi.ProviderEncoder; 037 import org.apache.directory.shared.ldap.message.spi.ProviderException; 038 import org.apache.directory.shared.ldap.util.StringTools; 039 import org.slf4j.Logger; 040 import org.slf4j.LoggerFactory; 041 042 043 /** 044 * LDAP BER provider's encoder. 045 * 046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 047 * @version $Rev: 912399 $ 048 */ 049 public class LdapEncoder implements ProviderEncoder 050 { 051 //TM private static long cumul = 0L; 052 //TM private static long count = 0L; 053 //TM private Object lock = new Object(); 054 055 /** The logger */ 056 private static Logger log = LoggerFactory.getLogger( LdapEncoder.class ); 057 058 /** A speedup for logger */ 059 private static final boolean IS_DEBUG = log.isDebugEnabled(); 060 061 /** The associated Provider */ 062 final Provider provider; 063 064 /** The callback to call when the encoding is done */ 065 private EncoderCallback encodeCallback; 066 067 068 /** 069 * Creates an instance of a Ldap Encoder implementation. 070 * 071 * @param provider The associated Provider 072 */ 073 public LdapEncoder( Provider provider ) 074 { 075 this.provider = provider; 076 encodeCallback = new OutputCallback(); 077 } 078 079 080 /** 081 * Encodes a LdapMessage, and calls the callback. 082 * 083 * @param lock Not used... 084 * @param out Not used ... 085 * @param obj The LdapMessage to encode 086 * @throws ProviderException If anything went wrong 087 */ 088 public void encodeBlocking( Object lock, OutputStream out, Object obj ) throws ProviderException 089 { 090 try 091 { 092 if ( IS_DEBUG ) 093 { 094 log.debug( "Encoding this LdapMessage : " + obj ); 095 } 096 097 ( ( OutputCallback ) encodeCallback ).attach( out ); 098 encodeCallback.encodeOccurred( null, ( ( LdapMessageCodec ) obj ).encode() ); 099 } 100 catch ( EncoderException e ) 101 { 102 log.error( I18n.err( I18n.ERR_04065, obj, e.getLocalizedMessage() ) ); 103 ProviderException pe = new ProviderException( provider, I18n.err( I18n.ERR_04065, obj, e.getLocalizedMessage() ) ); 104 throw pe; 105 } 106 } 107 108 109 /** 110 * Encodes a LdapMessage, and return a ByteBuffer containing the resulting 111 * PDU 112 * 113 * @param obj The LdapMessage to encode 114 * @return The ByteBuffer containing the PDU 115 * @throws ProviderException If anything went wrong 116 */ 117 public ByteBuffer encodeBlocking( Object obj ) throws ProviderException 118 { 119 try 120 { 121 if ( IS_DEBUG ) 122 { 123 log.debug( "Encoding this LdapMessage : " + obj ); 124 } 125 126 ByteBuffer pdu = ( ( LdapMessageCodec ) obj ).encode(); 127 128 if ( IS_DEBUG ) 129 { 130 log.debug( "Encoded PDU : " + StringTools.dumpBytes( pdu.array() ) ); 131 } 132 133 pdu.flip(); 134 return pdu; 135 } 136 catch ( EncoderException e ) 137 { 138 log.error( I18n.err( I18n.ERR_04065, obj, e.getLocalizedMessage() ) ); 139 ProviderException pe = new ProviderException( provider, I18n.err( I18n.ERR_04065, obj, e.getLocalizedMessage() ) ); 140 throw pe; 141 } 142 } 143 144 145 /** 146 * Encodes a LdapMessage, and return a byte array containing the resulting 147 * PDU 148 * 149 * @param obj The LdapMessage to encode 150 * @return The byte[] containing the PDU 151 * @throws ProviderException If anything went wrong 152 */ 153 public byte[] encodeToArray( Object obj ) throws ProviderException 154 { 155 try 156 { 157 if ( IS_DEBUG ) 158 { 159 log.debug( "Encoding this LdapMessage : " + obj ); 160 } 161 162 byte[] pdu = ( ( LdapMessageCodec ) obj ).encode().array(); 163 164 if ( IS_DEBUG ) 165 { 166 log.debug( "Encoded PDU : " + StringTools.dumpBytes( pdu ) ); 167 } 168 169 return pdu; 170 } 171 catch ( EncoderException e ) 172 { 173 log.error( I18n.err( I18n.ERR_04065, obj, e.getLocalizedMessage() ) ); 174 ProviderException pe = new ProviderException( provider, I18n.err( I18n.ERR_04065, obj, e.getLocalizedMessage() ) ); 175 throw pe; 176 } 177 } 178 179 180 /** 181 * Gets the Provider associated with this SPI implementation object. 182 * 183 * @return Provider The provider 184 */ 185 public Provider getProvider() 186 { 187 return provider; 188 } 189 190 191 /** 192 * Encodes a LdapMessage, and calls the callback 193 * 194 * @param obj The LdapMessage to encode 195 * @throws EncoderException If anything went wrong 196 */ 197 public void encode( Object obj ) throws EncoderException 198 { 199 //TM long t0 = System.nanoTime(); 200 ByteBuffer encoded = encodeBlocking( obj ); 201 encodeCallback.encodeOccurred( null, encoded ); 202 //TM long t1 = System.nanoTime(); 203 204 //TM synchronized (lock) 205 //TM { 206 //TM cumul += (t1 - t0); 207 //TM count++; 208 //TM 209 //TM 210 //TM if ( count % 1000L == 0) 211 //TM { 212 //TM System.out.println( "Encode cost : " + (cumul/count) ); 213 //TM cumul = 0L; 214 //TM } 215 //TM } 216 } 217 218 219 /** 220 * Set the callback called when the encoding is done. 221 * 222 * @param cb The callback. 223 */ 224 public void setCallback( EncoderCallback cb ) 225 { 226 encodeCallback = cb; 227 } 228 229 230 /** 231 * Not used ... 232 * 233 * @deprecated 234 */ 235 public void setEncoderMonitor( EncoderMonitor monitor ) 236 { 237 } 238 239 /** 240 * The inner class used to write the PDU to a channel. 241 */ 242 class OutputCallback implements EncoderCallback 243 { 244 /** The channel in which the PDU will be written */ 245 private WritableByteChannel channel = null; 246 247 248 /** 249 * Callback to deliver a fully encoded object. 250 * 251 * @param encoder the stateful encoder driving the callback 252 * @param encoded the object that was encoded 253 */ 254 public void encodeOccurred( StatefulEncoder encoder, Object encoded ) 255 { 256 try 257 { 258 ( ( ByteBuffer ) encoded ).flip(); 259 channel.write( ( ByteBuffer ) encoded ); 260 } 261 catch ( IOException e ) 262 { 263 ProviderException pe = new ProviderException( provider, I18n.err( I18n.ERR_04065, "", e.getLocalizedMessage() ) ); 264 throw pe; 265 } 266 } 267 268 269 /** 270 * Associate a channel to the callback 271 * 272 * @param channel The channel to use to write a PDU 273 */ 274 void attach( WritableByteChannel channel ) 275 { 276 this.channel = channel; 277 } 278 279 280 /** 281 * Associate a OutputStream to the callback. A channel will be created. 282 * 283 * @param out The OutputStream to use 284 */ 285 void attach( OutputStream out ) 286 { 287 this.channel = Channels.newChannel( out ); 288 } 289 } 290 291 292 private static ByteBuffer encodeAsn1( AddRequestCodec addRequest ) 293 { 294 //int length = computeLength( addRequest ); 295 return null; 296 } 297 298 299 private static ByteBuffer encodeAsn1( LdapMessageCodec message ) throws EncoderException 300 { 301 ByteBuffer buffer = null; 302 303 switch ( message.getMessageType() ) 304 { 305 case ABANDON_REQUEST : 306 return encodeAsn1( message ); 307 308 case ADD_REQUEST : 309 case ADD_RESPONSE : 310 case BIND_REQUEST : 311 case BIND_RESPONSE : 312 case COMPARE_REQUEST : 313 case COMPARE_RESPONSE : 314 case DEL_REQUEST : 315 case DEL_RESPONSE : 316 case EXTENDED_REQUEST : 317 case EXTENDED_RESPONSE : 318 case INTERMEDIATE_RESPONSE : 319 case MODIFY_REQUEST : 320 case MODIFY_RESPONSE : 321 case MODIFYDN_REQUEST : 322 case MODIFYDN_RESPONSE : 323 case SEARCH_REQUEST : 324 case SEARCH_RESULT_DONE : 325 case SEARCH_RESULT_ENTRY : 326 case SEARCH_RESULT_REFERENCE : 327 case UNBIND_REQUEST : 328 329 } 330 331 return buffer; 332 } 333 }