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    import org.apache.directory.shared.i18n.I18n;
032    
033    
034    public class ASN1OutputStream extends FilterOutputStream
035    {
036        public ASN1OutputStream(OutputStream os)
037        {
038            super( os );
039        }
040    
041    
042        public ASN1OutputStream(ByteBuffer out)
043        {
044            super( newOutputStream( out ) );
045        }
046    
047    
048        public static OutputStream newOutputStream( final ByteBuffer buf )
049        {
050            return new OutputStream()
051            {
052                public synchronized void write( int integer ) throws IOException
053                {
054                    buf.put( ( byte ) integer );
055                }
056    
057    
058                public synchronized void write( byte[] bytes, int off, int len ) throws IOException
059                {
060                    buf.put( bytes, off, len );
061                }
062            };
063        }
064    
065    
066        private void writeLength( int length ) throws IOException
067        {
068            if ( length > 127 )
069            {
070                int size = 1;
071                int val = length;
072    
073                while ( ( val >>>= 8 ) != 0 )
074                {
075                    size++;
076                }
077    
078                write( ( byte ) ( size | 0x80 ) );
079    
080                for ( int i = ( size - 1 ) * 8; i >= 0; i -= 8 )
081                {
082                    write( ( byte ) ( length >> i ) );
083                }
084            }
085            else
086            {
087                write( ( byte ) length );
088            }
089        }
090    
091    
092        void writeEncoded( int tag, byte[] bytes ) throws IOException
093        {
094            write( tag );
095            writeLength( bytes.length );
096            write( bytes );
097        }
098    
099    
100        public void writeObject( Object obj ) throws IOException
101        {
102            if ( obj == null )
103            {
104                writeNull();
105            }
106            else if ( obj instanceof DEREncodable )
107            {
108                ( ( DEREncodable ) obj ).encode( this );
109            }
110            else
111            {
112                throw new IOException( I18n.err( I18n.ERR_00024 ) );
113            }
114        }
115    
116    
117        protected void writeNull() throws IOException
118        {
119            write( DERObject.NULL );
120            write( DERObject.TERMINATOR );
121        }
122    }