001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.util.asn1;
019    
020    import java.io.ByteArrayOutputStream;
021    import java.io.IOException;
022    
023    /**
024     * DER UTF8String object.
025     */
026    public class DERUTF8String
027        extends DERObject
028        implements DERString
029    {
030        String  string;
031    
032        /**
033         * return an UTF8 string from the passed in object.
034         *
035         * @exception IllegalArgumentException if the object cannot be converted.
036         */
037        public static DERUTF8String getInstance(
038            Object  obj)
039        {
040            if (obj == null || obj instanceof DERUTF8String)
041            {
042                return (DERUTF8String)obj;
043            }
044    
045            if (obj instanceof ASN1OctetString)
046            {
047                return new DERUTF8String(((ASN1OctetString)obj).getOctets());
048            }
049    
050            if (obj instanceof ASN1TaggedObject)
051            {
052                return getInstance(((ASN1TaggedObject)obj).getObject());
053            }
054    
055            throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
056        }
057    
058        /**
059         * return an UTF8 String from a tagged object.
060         *
061         * @param obj the tagged object holding the object we want
062         * @param explicit true if the object is meant to be explicitly
063         *              tagged false otherwise.
064         * @exception IllegalArgumentException if the tagged object cannot
065         *               be converted.
066         */
067        public static DERUTF8String getInstance(
068            ASN1TaggedObject obj,
069            boolean          explicit)
070        {
071            return getInstance(obj.getObject());
072        }
073    
074        /**
075         * basic constructor - byte encoded string.
076         */
077        DERUTF8String(
078            byte[]   string)
079        {
080            int i = 0;
081            int length = 0;
082    
083            while (i < string.length)
084            {
085                length++;
086                if ((string[i] & 0xe0) == 0xe0)
087                {
088                    i += 3;
089                }
090                else if ((string[i] & 0xc0) == 0xc0)
091                {
092                    i += 2;
093                }
094                else
095                {
096                    i += 1;
097                }
098            }
099    
100            char[]  cs = new char[length];
101    
102            i = 0;
103            length = 0;
104    
105            while (i < string.length)
106            {
107                char    ch;
108    
109                if ((string[i] & 0xe0) == 0xe0)
110                {
111                    ch = (char)(((string[i] & 0x1f) << 12)
112                          | ((string[i + 1] & 0x3f) << 6) | (string[i + 2] & 0x3f));
113                    i += 3;
114                }
115                else if ((string[i] & 0xc0) == 0xc0)
116                {
117                    ch = (char)(((string[i] & 0x3f) << 6) | (string[i + 1] & 0x3f));
118                    i += 2;
119                }
120                else
121                {
122                    ch = (char)(string[i] & 0xff);
123                    i += 1;
124                }
125    
126                cs[length++] = ch;
127            }
128    
129            this.string = new String(cs);
130        }
131    
132        /**
133         * basic constructor
134         */
135        public DERUTF8String(
136            String   string)
137        {
138            this.string = string;
139        }
140    
141        public String getString()
142        {
143            return string;
144        }
145    
146        public int hashCode()
147        {
148            return this.getString().hashCode();
149        }
150    
151        public boolean equals(
152            Object  o)
153        {
154            if (!(o instanceof DERUTF8String))
155            {
156                return false;
157            }
158    
159            DERUTF8String  s = (DERUTF8String)o;
160    
161            return this.getString().equals(s.getString());
162        }
163    
164        void encode(
165            DEROutputStream  out)
166            throws IOException
167        {
168            char[]                  c = string.toCharArray();
169            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
170    
171            for (int i = 0; i != c.length; i++)
172            {
173                char    ch = c[i];
174    
175                if (ch < 0x0080)
176                {
177                    bOut.write(ch);
178                }
179                else if (ch < 0x0800)
180                {
181                    bOut.write(0xc0 | (ch >> 6));
182                    bOut.write(0x80 | (ch & 0x3f));
183                }
184                else
185                {
186                    bOut.write(0xe0 | (ch >> 12));
187                    bOut.write(0x80 | ((ch >> 6) & 0x3F));
188                    bOut.write(0x80 | (ch & 0x3F));
189                }
190            }
191    
192            out.writeEncoded(UTF8_STRING, bOut.toByteArray());
193        }
194    }