001    package org.apache.commons.ssl.asn1;
002    
003    import java.io.ByteArrayOutputStream;
004    import java.io.IOException;
005    import java.io.InputStream;
006    import java.io.OutputStream;
007    
008    public abstract class DERGenerator
009        extends ASN1Generator {
010        private boolean _tagged = false;
011        private boolean _isExplicit;
012        private int _tagNo;
013    
014        protected DERGenerator(
015            OutputStream out) {
016            super(out);
017        }
018    
019        public DERGenerator(
020            OutputStream out,
021            int tagNo,
022            boolean isExplicit) {
023            super(out);
024    
025            _tagged = true;
026            _isExplicit = isExplicit;
027            _tagNo = tagNo;
028        }
029    
030        private void writeLength(
031            OutputStream out,
032            int length)
033            throws IOException {
034            if (length > 127) {
035                int size = 1;
036                int val = length;
037    
038                while ((val >>>= 8) != 0) {
039                    size++;
040                }
041    
042                out.write((byte) (size | 0x80));
043    
044                for (int i = (size - 1) * 8; i >= 0; i -= 8) {
045                    out.write((byte) (length >> i));
046                }
047            } else {
048                out.write((byte) length);
049            }
050        }
051    
052        void writeDEREncoded(
053            OutputStream out,
054            int tag,
055            byte[] bytes)
056            throws IOException {
057            out.write(tag);
058            writeLength(out, bytes.length);
059            out.write(bytes);
060        }
061    
062        void writeDEREncoded(
063            int tag,
064            byte[] bytes)
065            throws IOException {
066            if (_tagged) {
067                int tagNum = _tagNo | DERTags.TAGGED;
068    
069                if (_isExplicit) {
070                    int newTag = _tagNo | DERTags.CONSTRUCTED | DERTags.TAGGED;
071    
072                    ByteArrayOutputStream bOut = new ByteArrayOutputStream();
073    
074                    writeDEREncoded(bOut, tag, bytes);
075    
076                    writeDEREncoded(_out, newTag, bOut.toByteArray());
077                } else {
078                    if ((tag & DERTags.CONSTRUCTED) != 0) {
079                        writeDEREncoded(_out, tagNum | DERTags.CONSTRUCTED, bytes);
080                    } else {
081                        writeDEREncoded(_out, tagNum, bytes);
082                    }
083                }
084            } else {
085                writeDEREncoded(_out, tag, bytes);
086            }
087        }
088    
089        void writeDEREncoded(
090            OutputStream out,
091            int tag,
092            InputStream in)
093            throws IOException {
094            out.write(tag);
095    
096            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
097    
098            int b = 0;
099            while ((b = in.read()) >= 0) {
100                bOut.write(b);
101            }
102    
103            byte[] bytes = bOut.toByteArray();
104    
105            writeLength(out, bytes.length);
106            out.write(bytes);
107        }
108    }