    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}