001package org.apache.commons.ssl.asn1;
002
003import java.io.IOException;
004import java.io.InputStream;
005
006public class BERTaggedObjectParser
007    implements ASN1TaggedObjectParser {
008    private int _baseTag;
009    private int _tagNumber;
010    private InputStream _contentStream;
011
012    private boolean _indefiniteLength;
013
014    protected BERTaggedObjectParser(
015        int baseTag,
016        int tagNumber,
017        InputStream contentStream) {
018        _baseTag = baseTag;
019        _tagNumber = tagNumber;
020        _contentStream = contentStream;
021        _indefiniteLength = contentStream instanceof IndefiniteLengthInputStream;
022    }
023
024    public boolean isConstructed() {
025        return (_baseTag & DERTags.CONSTRUCTED) != 0;
026    }
027
028    public int getTagNo() {
029        return _tagNumber;
030    }
031
032    public DEREncodable getObjectParser(
033        int tag,
034        boolean isExplicit)
035        throws IOException {
036        if (isExplicit) {
037            return new ASN1StreamParser(_contentStream).readObject();
038        } else {
039            switch (tag) {
040                case DERTags.SET:
041                    if (_indefiniteLength) {
042                        return new BERSetParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
043                    } else {
044                        return new DERSet(loadVector(_contentStream)).parser();
045                    }
046                case DERTags.SEQUENCE:
047                    if (_indefiniteLength) {
048                        return new BERSequenceParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
049                    } else {
050                        return new DERSequence(loadVector(_contentStream)).parser();
051                    }
052                case DERTags.OCTET_STRING:
053                    if (_indefiniteLength || this.isConstructed()) {
054                        return new BEROctetStringParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
055                    } else {
056                        return new DEROctetString(((DefiniteLengthInputStream) _contentStream).toByteArray()).parser();
057                    }
058            }
059        }
060
061        throw new RuntimeException("implicit tagging not implemented");
062    }
063
064    private ASN1EncodableVector loadVector(InputStream in)
065        throws IOException {
066        ASN1StreamParser aIn = new ASN1StreamParser(in);
067        ASN1EncodableVector v = new ASN1EncodableVector();
068        DEREncodable obj = aIn.readObject();
069
070        while (obj != null) {
071            v.add(obj.getDERObject());
072            obj = aIn.readObject();
073        }
074
075        return v;
076    }
077
078    private ASN1EncodableVector rLoadVector(InputStream in) {
079        try {
080            return loadVector(in);
081        }
082        catch (IOException e) {
083            throw new IllegalStateException(e.getMessage());
084        }
085    }
086
087    public DERObject getDERObject() {
088        if (_indefiniteLength) {
089            ASN1EncodableVector v = rLoadVector(_contentStream);
090
091            if (v.size() > 1) {
092                return new BERTaggedObject(false, _tagNumber, new BERSequence(v));
093            } else if (v.size() == 1) {
094                return new BERTaggedObject(true, _tagNumber, v.get(0));
095            } else {
096                return new BERTaggedObject(false, _tagNumber, new BERSequence());
097            }
098        } else {
099            if (this.isConstructed()) {
100                ASN1EncodableVector v = rLoadVector(_contentStream);
101
102                if (v.size() == 1) {
103                    return new DERTaggedObject(true, _tagNumber, v.get(0));
104                }
105
106                return new DERTaggedObject(false, _tagNumber, new DERSequence(v));
107            }
108
109            try {
110                return new DERTaggedObject(false, _tagNumber, new DEROctetString(((DefiniteLengthInputStream) _contentStream).toByteArray()));
111            }
112            catch (IOException e) {
113                throw new IllegalStateException(e.getMessage());
114            }
115        }
116
117    }
118}