001package org.apache.commons.ssl.org.bouncycastle.asn1.cms; 002 003import java.text.ParseException; 004import java.text.SimpleDateFormat; 005import java.util.Date; 006import java.util.Locale; 007import java.util.SimpleTimeZone; 008 009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Choice; 010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1GeneralizedTime; 011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object; 012import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 013import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject; 014import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1UTCTime; 015import org.apache.commons.ssl.org.bouncycastle.asn1.DERGeneralizedTime; 016import org.apache.commons.ssl.org.bouncycastle.asn1.DERUTCTime; 017 018/** 019 * <a href="http://tools.ietf.org/html/rfc5652#section-11.3">RFC 5652</a>: 020 * Dual-mode timestamp format producing either UTCTIme or GeneralizedTime. 021 * <p> 022 * <pre> 023 * Time ::= CHOICE { 024 * utcTime UTCTime, 025 * generalTime GeneralizedTime } 026 * </pre> 027 * <p> 028 * This has a constructor using java.util.Date for input which generates 029 * a {@link org.bouncycastle.asn1.DERUTCTime DERUTCTime} object if the 030 * supplied datetime is in range 1950-01-01-00:00:00 UTC until 2049-12-31-23:59:60 UTC. 031 * If the datetime value is outside that range, the generated object will be 032 * {@link org.bouncycastle.asn1.DERGeneralizedTime DERGeneralizedTime}. 033 */ 034public class Time 035 extends ASN1Object 036 implements ASN1Choice 037{ 038 ASN1Primitive time; 039 040 public static Time getInstance( 041 ASN1TaggedObject obj, 042 boolean explicit) 043 { 044 return getInstance(obj.getObject()); 045 } 046 047 /** 048 * @deprecated use getInstance() 049 */ 050 public Time( 051 ASN1Primitive time) 052 { 053 if (!(time instanceof ASN1UTCTime) 054 && !(time instanceof ASN1GeneralizedTime)) 055 { 056 throw new IllegalArgumentException("unknown object passed to Time"); 057 } 058 059 this.time = time; 060 } 061 062 /** 063 * Creates a time object from a given date - if the date is between 1950 064 * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime 065 * is used. 066 * 067 * @param time a date object representing the time of interest. 068 */ 069 public Time( 070 Date time) 071 { 072 SimpleTimeZone tz = new SimpleTimeZone(0, "Z"); 073 SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss"); 074 075 dateF.setTimeZone(tz); 076 077 String d = dateF.format(time) + "Z"; 078 int year = Integer.parseInt(d.substring(0, 4)); 079 080 if (year < 1950 || year > 2049) 081 { 082 this.time = new DERGeneralizedTime(d); 083 } 084 else 085 { 086 this.time = new DERUTCTime(d.substring(2)); 087 } 088 } 089 090 /** 091 * Creates a time object from a given date and locale - if the date is between 1950 092 * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime 093 * is used. You may need to use this constructor if the default locale 094 * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations. 095 * 096 * @param time a date object representing the time of interest. 097 * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value. 098 */ 099 public Time( 100 Date time, 101 Locale locale) 102 { 103 SimpleTimeZone tz = new SimpleTimeZone(0, "Z"); 104 SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale); 105 106 dateF.setTimeZone(tz); 107 108 String d = dateF.format(time) + "Z"; 109 int year = Integer.parseInt(d.substring(0, 4)); 110 111 if (year < 1950 || year > 2049) 112 { 113 this.time = new DERGeneralizedTime(d); 114 } 115 else 116 { 117 this.time = new DERUTCTime(d.substring(2)); 118 } 119 } 120 121 /** 122 * Return a Time object from the given object. 123 * <p> 124 * Accepted inputs: 125 * <ul> 126 * <li> null → null 127 * <li> {@link Time} object 128 * <li> {@link org.bouncycastle.asn1.DERUTCTime DERUTCTime} object 129 * <li> {@link org.bouncycastle.asn1.DERGeneralizedTime DERGeneralizedTime} object 130 * </ul> 131 * 132 * @param obj the object we want converted. 133 * @exception IllegalArgumentException if the object cannot be converted. 134 */ 135 public static Time getInstance( 136 Object obj) 137 { 138 if (obj == null || obj instanceof Time) 139 { 140 return (Time)obj; 141 } 142 else if (obj instanceof ASN1UTCTime) 143 { 144 return new Time((ASN1UTCTime)obj); 145 } 146 else if (obj instanceof ASN1GeneralizedTime) 147 { 148 return new Time((ASN1GeneralizedTime)obj); 149 } 150 151 throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName()); 152 } 153 154 /** 155 * Get the date+tine as a String in full form century format. 156 */ 157 public String getTime() 158 { 159 if (time instanceof ASN1UTCTime) 160 { 161 return ((ASN1UTCTime)time).getAdjustedTime(); 162 } 163 else 164 { 165 return ((ASN1GeneralizedTime)time).getTime(); 166 } 167 } 168 169 /** 170 * Get java.util.Date version of date+time. 171 */ 172 public Date getDate() 173 { 174 try 175 { 176 if (time instanceof ASN1UTCTime) 177 { 178 return ((ASN1UTCTime)time).getAdjustedDate(); 179 } 180 else 181 { 182 return ((ASN1GeneralizedTime)time).getDate(); 183 } 184 } 185 catch (ParseException e) 186 { // this should never happen 187 throw new IllegalStateException("invalid date string: " + e.getMessage()); 188 } 189 } 190 191 /** 192 * Produce an object suitable for an ASN1OutputStream. 193 */ 194 public ASN1Primitive toASN1Primitive() 195 { 196 return time; 197 } 198}