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