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.crypto.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 }