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 }