001    /*
002     * Copyright (c) 2000 - 2006 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
003     * 
004     * Permission is hereby granted, free of charge, to any person obtaining a copy of this
005     * software and associated documentation files (the "Software"), to deal in the Software
006     * without restriction, including without limitation the rights to use, copy, modify,
007     * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
008     * permit persons to whom the Software is furnished to do so, subject to the following
009     * conditions:
010     * 
011     * The above copyright notice and this permission notice shall be included in all copies
012     * or substantial portions of the Software.
013     * 
014     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
015     * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
016     * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
017     * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
018     * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
019     * DEALINGS IN THE SOFTWARE.
020     * 
021     */
022    
023    package org.apache.directory.shared.asn1.der;
024    
025    
026    import java.io.FilterOutputStream;
027    import java.io.IOException;
028    import java.io.OutputStream;
029    import java.nio.ByteBuffer;
030    
031    
032    public class ASN1OutputStream extends FilterOutputStream
033    {
034        public ASN1OutputStream(OutputStream os)
035        {
036            super( os );
037        }
038    
039    
040        public ASN1OutputStream(ByteBuffer out)
041        {
042            super( newOutputStream( out ) );
043        }
044    
045    
046        public static OutputStream newOutputStream( final ByteBuffer buf )
047        {
048            return new OutputStream()
049            {
050                public synchronized void write( int integer ) throws IOException
051                {
052                    buf.put( ( byte ) integer );
053                }
054    
055    
056                public synchronized void write( byte[] bytes, int off, int len ) throws IOException
057                {
058                    buf.put( bytes, off, len );
059                }
060            };
061        }
062    
063    
064        private void writeLength( int length ) throws IOException
065        {
066            if ( length > 127 )
067            {
068                int size = 1;
069                int val = length;
070    
071                while ( ( val >>>= 8 ) != 0 )
072                {
073                    size++;
074                }
075    
076                write( ( byte ) ( size | 0x80 ) );
077    
078                for ( int i = ( size - 1 ) * 8; i >= 0; i -= 8 )
079                {
080                    write( ( byte ) ( length >> i ) );
081                }
082            }
083            else
084            {
085                write( ( byte ) length );
086            }
087        }
088    
089    
090        void writeEncoded( int tag, byte[] bytes ) throws IOException
091        {
092            write( tag );
093            writeLength( bytes.length );
094            write( bytes );
095        }
096    
097    
098        public void writeObject( Object obj ) throws IOException
099        {
100            if ( obj == null )
101            {
102                writeNull();
103            }
104            else if ( obj instanceof DEREncodable )
105            {
106                ( ( DEREncodable ) obj ).encode( this );
107            }
108            else
109            {
110                throw new IOException( "Object not DEREncodable." );
111            }
112        }
113    
114    
115        protected void writeNull() throws IOException
116        {
117            write( DERObject.NULL );
118            write( DERObject.TERMINATOR );
119        }
120    }