001    package org.apache.commons.ssl.asn1;
002    
003    import java.io.IOException;
004    import java.io.InputStream;
005    
006    public 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    }