001    /**
002     *
003     *  Licensed to the Apache Software Foundation (ASF) under one or more
004     *  contributor license agreements.  See the NOTICE file distributed with
005     *  this work for additional information regarding copyright ownership.
006     *  The ASF licenses this file to You under the Apache License, Version 2.0
007     *  (the "License"); you may not use this file except in compliance with
008     *  the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     *  Unless required by applicable law or agreed to in writing, software
013     *  distributed under the License is distributed on an "AS IS" BASIS,
014     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     *  See the License for the specific language governing permissions and
016     *  limitations under the License.
017     */
018    
019    package org.apache.geronimo.util.asn1;
020    
021    import java.io.ByteArrayOutputStream;
022    import java.io.EOFException;
023    import java.io.IOException;
024    import java.io.InputStream;
025    import java.util.Vector;
026    
027    /**
028     * @deprecated use ASN1InputStream
029     */
030    public class BERInputStream
031        extends DERInputStream
032    {
033        private DERObject END_OF_STREAM = new DERObject() {
034                                            void encode(
035                                                DEROutputStream out)
036                                            throws IOException
037                                            {
038                                                throw new IOException("Eeek!");
039                                            }
040                                            public int hashCode()
041                                            {
042                                                return 0;
043                                            }
044                                            public boolean equals(
045                                                Object o)
046                                            {
047                                                return o == this;
048                                            }
049                                        };
050        public BERInputStream(
051            InputStream is)
052        {
053            super(is);
054        }
055    
056        /**
057         * read a string of bytes representing an indefinite length object.
058         */
059        private byte[] readIndefiniteLengthFully()
060            throws IOException
061        {
062            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
063            int                     b, b1;
064    
065            b1 = read();
066    
067            while ((b = read()) >= 0)
068            {
069                if (b1 == 0 && b == 0)
070                {
071                    break;
072                }
073    
074                bOut.write(b1);
075                b1 = b;
076            }
077    
078            return bOut.toByteArray();
079        }
080    
081        private BERConstructedOctetString buildConstructedOctetString()
082            throws IOException
083        {
084            Vector               octs = new Vector();
085    
086            for (;;)
087            {
088                DERObject        o = readObject();
089    
090                if (o == END_OF_STREAM)
091                {
092                    break;
093                }
094    
095                octs.addElement(o);
096            }
097    
098            return new BERConstructedOctetString(octs);
099        }
100    
101        public DERObject readObject()
102            throws IOException
103        {
104            int tag = read();
105            if (tag == -1)
106            {
107                throw new EOFException();
108            }
109    
110            int     length = readLength();
111    
112            if (length < 0)    // indefinite length method
113            {
114                switch (tag)
115                {
116                case NULL:
117                    return null;
118                case SEQUENCE | CONSTRUCTED:
119                    BERConstructedSequence  seq = new BERConstructedSequence();
120    
121                    for (;;)
122                    {
123                        DERObject   obj = readObject();
124    
125                        if (obj == END_OF_STREAM)
126                        {
127                            break;
128                        }
129    
130                        seq.addObject(obj);
131                    }
132                    return seq;
133                case OCTET_STRING | CONSTRUCTED:
134                    return buildConstructedOctetString();
135                case SET | CONSTRUCTED:
136                    ASN1EncodableVector  v = new ASN1EncodableVector();
137    
138                    for (;;)
139                    {
140                        DERObject   obj = readObject();
141    
142                        if (obj == END_OF_STREAM)
143                        {
144                            break;
145                        }
146    
147                        v.add(obj);
148                    }
149                    return new BERSet(v);
150                default:
151                    //
152                    // with tagged object tag number is bottom 5 bits
153                    //
154                    if ((tag & TAGGED) != 0)
155                    {
156                        if ((tag & 0x1f) == 0x1f)
157                        {
158                            throw new IOException("unsupported high tag encountered");
159                        }
160    
161                        //
162                        // simple type - implicit... return an octet string
163                        //
164                        if ((tag & CONSTRUCTED) == 0)
165                        {
166                            byte[]  bytes = readIndefiniteLengthFully();
167    
168                            return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
169                        }
170    
171                        //
172                        // either constructed or explicitly tagged
173                        //
174                        DERObject        dObj = readObject();
175    
176                        if (dObj == END_OF_STREAM)     // empty tag!
177                        {
178                            return new DERTaggedObject(tag & 0x1f);
179                        }
180    
181                        DERObject       next = readObject();
182    
183                        //
184                        // explicitly tagged (probably!) - if it isn't we'd have to
185                        // tell from the context
186                        //
187                        if (next == END_OF_STREAM)
188                        {
189                            return new BERTaggedObject(tag & 0x1f, dObj);
190                        }
191    
192                        //
193                        // another implicit object, we'll create a sequence...
194                        //
195                        seq = new BERConstructedSequence();
196    
197                        seq.addObject(dObj);
198    
199                        do
200                        {
201                            seq.addObject(next);
202                            next = readObject();
203                        }
204                        while (next != END_OF_STREAM);
205    
206                        return new BERTaggedObject(false, tag & 0x1f, seq);
207                    }
208    
209                    throw new IOException("unknown BER object encountered");
210                }
211            }
212            else
213            {
214                if (tag == 0 && length == 0)    // end of contents marker.
215                {
216                    return END_OF_STREAM;
217                }
218    
219                byte[]  bytes = new byte[length];
220    
221                readFully(bytes);
222    
223                return buildObject(tag, bytes);
224            }
225        }
226    }