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.SimpleDateFormat;
023    import java.util.Date;
024    import java.util.SimpleTimeZone;
025    
026    /**
027     * UTC time object.
028     */
029    public class DERUTCTime
030        extends DERObject
031    {
032        String      time;
033    
034        /**
035         * return an UTC Time from the passed in object.
036         *
037         * @exception IllegalArgumentException if the object cannot be converted.
038         */
039        public static DERUTCTime getInstance(
040            Object  obj)
041        {
042            if (obj == null || obj instanceof DERUTCTime)
043            {
044                return (DERUTCTime)obj;
045            }
046    
047            if (obj instanceof ASN1OctetString)
048            {
049                return new DERUTCTime(((ASN1OctetString)obj).getOctets());
050            }
051    
052            throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
053        }
054    
055        /**
056         * return an UTC Time from a tagged object.
057         *
058         * @param obj the tagged object holding the object we want
059         * @param explicit true if the object is meant to be explicitly
060         *              tagged false otherwise.
061         * @exception IllegalArgumentException if the tagged object cannot
062         *               be converted.
063         */
064        public static DERUTCTime getInstance(
065            ASN1TaggedObject obj,
066            boolean          explicit)
067        {
068            return getInstance(obj.getObject());
069        }
070    
071        /**
072         * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
073         * never encoded. When you're creating one of these objects from scratch, that's
074         * what you want to use, otherwise we'll try to deal with whatever gets read from
075         * the input stream... (this is why the input format is different from the getTime()
076         * method output).
077         * <p>
078         *
079         * @param time the time string.
080         */
081        public DERUTCTime(
082            String  time)
083        {
084            this.time = time;
085        }
086    
087        /**
088         * base constructer from a java.util.date object
089         */
090        public DERUTCTime(
091            Date time)
092        {
093            SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
094    
095            dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
096    
097            this.time = dateF.format(time);
098        }
099    
100        DERUTCTime(
101            byte[]  bytes)
102        {
103            //
104            // explicitly convert to characters
105            //
106            char[]  dateC = new char[bytes.length];
107    
108            for (int i = 0; i != dateC.length; i++)
109            {
110                dateC[i] = (char)(bytes[i] & 0xff);
111            }
112    
113            this.time = new String(dateC);
114        }
115    
116        /**
117         * return the time - always in the form of
118         *  YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
119         * <p>
120         * Normally in a certificate we would expect "Z" rather than "GMT",
121         * however adding the "GMT" means we can just use:
122         * <pre>
123         *     dateF = new SimpleDateFormat("yyMMddHHmmssz");
124         * </pre>
125         * To read in the time and get a date which is compatible with our local
126         * time zone.
127         * <p>
128         * <b>Note:</b> In some cases, due to the local date processing, this
129         * may lead to unexpected results. If you want to stick the normal
130         * convention of 1950 to 2049 use the getAdjustedTime() method.
131         */
132        public String getTime()
133        {
134            //
135            // standardise the format.
136            //
137            if (time.length() == 11)
138            {
139                return time.substring(0, 10) + "00GMT+00:00";
140            }
141            else if (time.length() == 13)
142            {
143                return time.substring(0, 12) + "GMT+00:00";
144            }
145            else if (time.length() == 17)
146            {
147                return time.substring(0, 12) + "GMT" + time.substring(12, 15) + ":" + time.substring(15, 17);
148            }
149    
150            return time;
151        }
152    
153        /**
154         * return the time as an adjusted date with a 4 digit year. This goes
155         * in the range of 1950 - 2049.
156         */
157        public String getAdjustedTime()
158        {
159            String   d = this.getTime();
160    
161            if (d.charAt(0) < '5')
162            {
163                return "20" + d;
164            }
165            else
166            {
167                return "19" + d;
168            }
169        }
170    
171        private byte[] getOctets()
172        {
173            char[]  cs = time.toCharArray();
174            byte[]  bs = new byte[cs.length];
175    
176            for (int i = 0; i != cs.length; i++)
177            {
178                bs[i] = (byte)cs[i];
179            }
180    
181            return bs;
182        }
183    
184        void encode(
185            DEROutputStream  out)
186            throws IOException
187        {
188            out.writeEncoded(UTC_TIME, this.getOctets());
189        }
190    
191        public boolean equals(
192            Object  o)
193        {
194            if ((o == null) || !(o instanceof DERUTCTime))
195            {
196                return false;
197            }
198    
199            return time.equals(((DERUTCTime)o).time);
200        }
201    
202        public int hashCode()
203        {
204            return time.hashCode();
205        }
206    }