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.IOException;
022    import java.text.ParseException;
023    import java.text.SimpleDateFormat;
024    import java.util.Date;
025    import java.util.SimpleTimeZone;
026    
027    /**
028     * Generalized time object.
029     */
030    public class DERGeneralizedTime
031        extends DERObject
032    {
033        String      time;
034    
035        /**
036         * return a generalized time from the passed in object
037         *
038         * @exception IllegalArgumentException if the object cannot be converted.
039         */
040        public static DERGeneralizedTime getInstance(
041            Object  obj)
042        {
043            if (obj == null || obj instanceof DERGeneralizedTime)
044            {
045                return (DERGeneralizedTime)obj;
046            }
047    
048            if (obj instanceof ASN1OctetString)
049            {
050                return new DERGeneralizedTime(((ASN1OctetString)obj).getOctets());
051            }
052    
053            throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
054        }
055    
056        /**
057         * return a Generalized Time object from a tagged object.
058         *
059         * @param obj the tagged object holding the object we want
060         * @param explicit true if the object is meant to be explicitly
061         *              tagged false otherwise.
062         * @exception IllegalArgumentException if the tagged object cannot
063         *               be converted.
064         */
065        public static DERGeneralizedTime getInstance(
066            ASN1TaggedObject obj,
067            boolean          explicit)
068        {
069            return getInstance(obj.getObject());
070        }
071    
072        /**
073         * The correct format for this is YYYYMMDDHHMMSSZ, or without the Z
074         * for local time, or Z+-HHMM on the end, for difference between local
075         * time and UTC time.
076         * <p>
077         *
078         * @param time the time string.
079         */
080        public DERGeneralizedTime(
081            String  time)
082        {
083            this.time = time;
084        }
085    
086        /**
087         * base constructer from a java.util.date object
088         */
089        public DERGeneralizedTime(
090            Date time)
091        {
092            SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
093    
094            dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
095    
096            this.time = dateF.format(time);
097        }
098    
099        DERGeneralizedTime(
100            byte[]  bytes)
101        {
102            //
103            // explicitly convert to characters
104            //
105            char[]  dateC = new char[bytes.length];
106    
107            for (int i = 0; i != dateC.length; i++)
108            {
109                dateC[i] = (char)(bytes[i] & 0xff);
110            }
111    
112            this.time = new String(dateC);
113        }
114    
115        /**
116         * return the time - always in the form of
117         *  YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
118         * <p>
119         * Normally in a certificate we would expect "Z" rather than "GMT",
120         * however adding the "GMT" means we can just use:
121         * <pre>
122         *     dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
123         * </pre>
124         * To read in the time and get a date which is compatible with our local
125         * time zone.
126         */
127        public String getTime()
128        {
129            //
130            // standardise the format.
131            //
132            if (time.charAt(time.length() - 1) == 'Z')
133            {
134                return time.substring(0, time.length() - 1) + "GMT+00:00";
135            }
136            else
137            {
138                int signPos = time.length() - 5;
139                char sign = time.charAt(signPos);
140                if (sign == '-' || sign == '+')
141                {
142                    return time.substring(0, signPos)
143                        + "GMT"
144                        + time.substring(signPos, signPos + 3)
145                        + ":"
146                        + time.substring(signPos + 3);
147                }
148                else
149                {
150                    signPos = time.length() - 3;
151                    sign = time.charAt(signPos);
152                    if (sign == '-' || sign == '+')
153                    {
154                        return time.substring(0, signPos)
155                            + "GMT"
156                            + time.substring(signPos)
157                            + ":00";
158                    }
159                }
160            }
161    
162            return time;
163        }
164    
165        public Date getDate()
166            throws ParseException
167        {
168            SimpleDateFormat dateF;
169    
170            if (time.indexOf('.') == 14)
171            {
172                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
173            }
174            else
175            {
176                dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
177            }
178    
179            dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
180    
181            return dateF.parse(time);
182        }
183    
184        private byte[] getOctets()
185        {
186            char[]  cs = time.toCharArray();
187            byte[]  bs = new byte[cs.length];
188    
189            for (int i = 0; i != cs.length; i++)
190            {
191                bs[i] = (byte)cs[i];
192            }
193    
194            return bs;
195        }
196    
197    
198        void encode(
199            DEROutputStream  out)
200            throws IOException
201        {
202            out.writeEncoded(GENERALIZED_TIME, this.getOctets());
203        }
204    
205        public boolean equals(
206            Object  o)
207        {
208            if ((o == null) || !(o instanceof DERGeneralizedTime))
209            {
210                return false;
211            }
212    
213            return time.equals(((DERGeneralizedTime)o).time);
214        }
215    
216        public int hashCode()
217        {
218            return time.hashCode();
219        }
220    }