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.asn1.codec.stateful.examples;
021    
022    
023    import java.nio.ByteBuffer;
024    
025    import org.apache.directory.shared.asn1.codec.EncoderException;
026    import org.apache.directory.shared.asn1.codec.stateful.EncoderCallback;
027    import org.apache.directory.shared.asn1.codec.stateful.EncoderMonitor;
028    import org.apache.directory.shared.asn1.codec.stateful.EncoderMonitorAdapter;
029    import org.apache.directory.shared.asn1.codec.stateful.StatefulEncoder;
030    
031    
032    /**
033     * Document me.
034     * 
035     * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
036     * @version $Rev: 664290 $
037     */
038    public class HexEncoder implements StatefulEncoder
039    {
040        private static final int CHUNK_SZ = 128;
041    
042        private ByteBuffer buf = ByteBuffer.allocate( CHUNK_SZ );
043    
044        private EncoderMonitor monitor = new EncoderMonitorAdapter();
045    
046        private EncoderCallback cb = new EncoderCallback()
047        {
048            public void encodeOccurred( StatefulEncoder encoder, Object encoded )
049            {
050            }
051        };
052    
053        private final byte[] HEXCHAR_LUT =
054            { ( byte ) '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
055    
056    
057        /**
058         * Transforms a decoded ByteArray of binary data into a stream of ASCII hex
059         * characters.
060         * 
061         * @param obj
062         * @throws org.apache.directory.shared.asn1.codec.EncoderException
063         */
064        public void encode( Object obj ) throws EncoderException
065        {
066            ByteBuffer raw = ( ByteBuffer ) obj;
067    
068            if ( raw == null || !raw.hasRemaining() )
069            {
070                return;
071            }
072    
073            /*
074             * Keep encoding one byte at a time if we have remaining bytes in the
075             * raw buffer and there's space for 2 hex character bytes in the
076             * resultant hex encoded buffer.
077             */
078            while ( raw.hasRemaining() )
079            {
080                if ( !buf.hasRemaining() )
081                {
082                    buf.flip();
083                    cb.encodeOccurred( this, buf );
084                    monitor.callbackOccured( this, cb, buf );
085                    buf.clear();
086                }
087    
088                byte bite = raw.get();
089                buf.put( HEXCHAR_LUT[( bite >> 4 ) & 0x0000000F] );
090                buf.put( HEXCHAR_LUT[bite & 0x0000000F] );
091            }
092    
093            buf.flip();
094            cb.encodeOccurred( this, buf );
095            monitor.callbackOccured( this, cb, buf );
096            buf.clear();
097        }
098    
099    
100        public void setCallback( EncoderCallback cb )
101        {
102            EncoderCallback old = this.cb;
103            this.cb = cb;
104            monitor.callbackSet( this, old, cb );
105        }
106    
107    
108        public void setEncoderMonitor( EncoderMonitor monitor )
109        {
110            this.monitor = monitor;
111        }
112    }