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 }