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