001    package org.apache.commons.ssl.asn1;
002    
003    import java.io.IOException;
004    import java.util.Enumeration;
005    
006    /**
007     * BER TaggedObject - in ASN.1 nottation this is any object proceeded by
008     * a [n] where n is some number - these are assume to follow the construction
009     * rules (as with sequences).
010     */
011    public class BERTaggedObject
012        extends DERTaggedObject {
013        /**
014         * @param tagNo the tag number for this object.
015         * @param obj   the tagged object.
016         */
017        public BERTaggedObject(
018            int tagNo,
019            DEREncodable obj) {
020            super(tagNo, obj);
021        }
022    
023        /**
024         * @param explicit true if an explicitly tagged object.
025         * @param tagNo    the tag number for this object.
026         * @param obj      the tagged object.
027         */
028        public BERTaggedObject(
029            boolean explicit,
030            int tagNo,
031            DEREncodable obj) {
032            super(explicit, tagNo, obj);
033        }
034    
035        /**
036         * create an implicitly tagged object that contains a zero
037         * length sequence.
038         */
039        public BERTaggedObject(
040            int tagNo) {
041            super(false, tagNo, new BERSequence());
042        }
043    
044        void encode(
045            DEROutputStream out)
046            throws IOException {
047            if (out instanceof ASN1OutputStream || out instanceof BEROutputStream) {
048                out.write(CONSTRUCTED | TAGGED | tagNo);
049                out.write(0x80);
050    
051                if (!empty) {
052                    if (!explicit) {
053                        if (obj instanceof ASN1OctetString) {
054                            Enumeration e;
055    
056                            if (obj instanceof BERConstructedOctetString) {
057                                e = ((BERConstructedOctetString) obj).getObjects();
058                            } else {
059                                ASN1OctetString octs = (ASN1OctetString) obj;
060                                BERConstructedOctetString berO = new BERConstructedOctetString(octs.getOctets());
061    
062                                e = berO.getObjects();
063                            }
064    
065                            while (e.hasMoreElements()) {
066                                out.writeObject(e.nextElement());
067                            }
068                        } else if (obj instanceof ASN1Sequence) {
069                            Enumeration e = ((ASN1Sequence) obj).getObjects();
070    
071                            while (e.hasMoreElements()) {
072                                out.writeObject(e.nextElement());
073                            }
074                        } else if (obj instanceof ASN1Set) {
075                            Enumeration e = ((ASN1Set) obj).getObjects();
076    
077                            while (e.hasMoreElements()) {
078                                out.writeObject(e.nextElement());
079                            }
080                        } else {
081                            throw new RuntimeException("not implemented: " + obj.getClass().getName());
082                        }
083                    } else {
084                        out.writeObject(obj);
085                    }
086                }
087    
088                out.write(0x00);
089                out.write(0x00);
090            } else {
091                super.encode(out);
092            }
093        }
094    }