Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*************************************************************************
* *
* CESeCore: CE Security Core *
* *
* This software is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or any later version. *
* *
* See terms of license at gnu.org. *
* *
*************************************************************************/
package org.cesecore.util;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang.time.FastDateFormat;
import org.apache.log4j.Logger;
/**
* Class for encoding and decoding certificate validity and end date.
*
* @version $Id: ValidityDate.java 26461 2017-08-29 23:09:05Z anatom $
*/
public class ValidityDate {
/** The date and time format defined in ISO8601. The 'T' can be omitted (and we do to save some parsing cycles). */
public static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd HH:mm:ssZZ";
public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");
public static final TimeZone TIMEZONE_SERVER = TimeZone.getDefault();
private static final Logger log = Logger.getLogger(ValidityDate.class);
// Time format for storage where implied timezone is UTC
private static final String[] IMPLIED_UTC_PATTERN = {"yyyy-MM-dd HH:mm"};
private static final String[] IMPLIED_UTC_PATTERN_TZ = {"yyyy-MM-dd HH:mmZZ"};
// Time format for human interactions
private static final String[] ISO8601_PATTERNS = {
// These must have timezone on date-only format also, since it has a time also (which is 00:00).
// If the timezone is omitted then the string "+00:00" is appended to the date before parsing
ISO8601_DATE_FORMAT, "yyyy-MM-dd HH:mmZZ", "yyyy-MM-ddZZ"
};
// Can't be instantiated
private ValidityDate() {
}
/** Parse a String in the format "yyyy-MM-dd HH:mm" as a date with implied TimeZone UTC. */
public static Date parseAsUTC(final String dateString) throws ParseException {
return DateUtils.parseDateStrictly(dateString+"+00:00", IMPLIED_UTC_PATTERN_TZ);
}
/** Parse a String in the format "yyyy-MM-dd HH:mm:ssZZ". The hour/minutes, seconds and timezone are optional parts. */
public static Date parseAsIso8601(final String dateString) throws ParseException {
try {
return DateUtils.parseDateStrictly(dateString, ISO8601_PATTERNS);
} catch (ParseException e) {
// Try again with timezone. In DateUtils, the default timezone seems to be the server
// timezone and not UTC, so we can't have date formats without "ZZ".
return DateUtils.parseDateStrictly(dateString+"+00:00", ISO8601_PATTERNS);
}
}
/**
*
* @param dateString a string describing a date
* @return true if dateString is in the format "yyyy-MM-dd HH:mm:ssZZ"
*/
public static boolean isValidIso8601Date(final String dateString) {
try {
if(StringUtils.isEmpty(dateString)) {
return false;
} else {
parseAsIso8601(dateString);
}
return true;
} catch(ParseException e) {
return false;
}
}
/** Convert a Date to the format "yyyy-MM-dd HH:mm" with implied TimeZone UTC. */
public static String formatAsUTC(final Date date) {
return FastDateFormat.getInstance(IMPLIED_UTC_PATTERN[0], TIMEZONE_UTC).format(date);
}
/** Convert a absolute number of milliseconds to the format "yyyy-MM-dd HH:mm" with implied TimeZone UTC. */
public static String formatAsUTC(final long millis) {
return FastDateFormat.getInstance(IMPLIED_UTC_PATTERN[0], TIMEZONE_UTC).format(millis);
}
/** Convert a Date to the format "yyyy-MM-dd HH:mm:ssZZ" (the T is not required). The server's time zone is used. */
public static String formatAsISO8601(final Date date, final TimeZone timeZone) {
return FastDateFormat.getInstance(ISO8601_PATTERNS[0], timeZone).format(date);
}
/** Convert a Date in milliseconds to the format "yyyy-MM-dd HH:mm:ssZZ". The server's time zone is used. */
public static String formatAsISO8601ServerTZ(final long millis, final TimeZone timeZone) {
return FastDateFormat.getInstance(ISO8601_PATTERNS[0], TIMEZONE_SERVER).format(millis);
}
/** Convert a the format "yyyy-MM-dd HH:mm:ssZZ" to "yyyy-MM-dd HH:mm" with implied TimeZone UTC. */
public static String getImpliedUTCFromISO8601(final String dateString) throws ParseException {
return formatAsUTC(parseAsIso8601(dateString));
}
/** Convert a the format "yyyy-MM-dd HH:mm" with implied TimeZone UTC to "yyyy-MM-dd HH:mm:ssZZ". */
public static String getISO8601FromImpliedUTC(final String dateString, final TimeZone timeZone) throws ParseException {
return formatAsISO8601(parseAsUTC(dateString), timeZone);
}
/**
* Encoding of the validity for a CA or certificate profile. Either delta time or end date.
* @param validity *y *mo *d or absolute date in the form "yyyy-MM-dd HH:mm:ssZZ"
* @return delta time in days if h*m*d*; milliseconds since epoch if valid absolute date; -1 if neither
* @throws IllegalArgumentException if the argument is null
*/
@Deprecated
public static long encodeBeforeVersion661(final String validity) {
long result = -1;
try {
// parse ISO8601 time stamp, i.e 'yyyy-MM-dd HH:mm:ssZZ'.
result = parseAsIso8601(validity).getTime();
} catch (ParseException e) {
try {
// parse SimpleTime string with format '*y *mo *d ...'.
final long days = SimpleTime.getDaysFormat().parseMillis(validity) / (1000 * 60 * 60 *24);
if (days > 0) {
if (isDeltaTimeBeforeVersion661(days)) {
result = days;
} else {
result = Long.valueOf(Integer.MAX_VALUE-1);
log.info(validity + " is relative time format, but too far in the future. Limiting to " + result + " days.");
}
}
} catch(NumberFormatException nfe) {
if (log.isDebugEnabled()) {
log.debug("Cannot decode '" + validity + "' as ISO8601 date or relative time format ('3y 6mo 10d').");
}
}
}
return result;
}
/**
* Decodes encoded value to string in the form "yyyy-MM-dd HH:mm:ssZZ" or "1234d" (relative days).
* @param lEncoded If this is below Integer.MAX_VALUE it is interpreted as a number of days to firstDate, otherwise an unix timestamp.
*/
@Deprecated
public static String getStringBeforeVersion661(final long lEncoded) {
if (isDeltaTimeBeforeVersion661(lEncoded)) {
return SimpleTime.toString(lEncoded * 24 * 60 * 60 * 1000, SimpleTime.TYPE_DAYS);
}
return formatAsISO8601ServerTZ(lEncoded, TIMEZONE_SERVER);
}
/**
* Decodes encoded value to Date.
* @param lEncoded encoded value. If this is below Integer.MAX_VALUE it is interpreted as a number of days to firstDate, otherwise an unix timestamp.
* @param firstDate date to be used if encoded value is a delta time. Can never be null.
*/
@Deprecated
public static Date getDateBeforeVersion661(final long lEncoded, final Date firstDate) {
if (isDeltaTimeBeforeVersion661(lEncoded) ) {
return new Date(firstDate.getTime() + (lEncoded * 24 * 60 * 60 * 1000));
}
return new Date(lEncoded);
}
/**
* Decodes encoded value to Date.
* @param encodedValidity a relative time string (SimpleTime) or a date in ISO8601 format.
* @param firstDate date to be used if encoded validity is a relative time.
* @return the end date or null if a date or relative time could not be read.
* @see org.cesecore.util.SimpleTime
* @see org.cesecore.util.ValidityDate
*/
public static Date getDate(final String encodedValidity, final Date firstDate) {
try {
// We think this is the most common, so try this first, it's fail-fast
final long millis = SimpleTime.parseMillies(encodedValidity);
final Date endDate = new Date(firstDate.getTime() + millis);
return endDate;
} catch(NumberFormatException nfe) {
if (log.isDebugEnabled()) {
log.debug("Could not read encoded validity as relative date: " +encodedValidity+", "+ nfe.getMessage());
}
try {
return parseAsIso8601(encodedValidity);
} catch(ParseException p) {
log.error("Could not read encoded validity: " +encodedValidity+", "+ p.getMessage());
return null;
}
}
}
/** If below the integer capacity we have stored a relative date in days, otherwise it is an absolute time in milliseconds. */
@Deprecated
public static boolean isDeltaTimeBeforeVersion661(final long lEncoded) {
return lEncoded < Integer.MAX_VALUE; // This could probably be <= instead??
}
/**
* Parse a date as either "yyyy-MM-dd HH:mm:ssZZ" or a relative hex encoded UNIX time stamp (in seconds).
* Use for parsing of the build time property "ca.toolateexpiredate" in ejbca.properties.
* @return the date or the largest possible Date if unable to parse the argument.
*/
public static Date parseCaLatestValidDateTime(final String sDate) {
Date tooLateExpireDate = null;
if (sDate.length()>0) {
//First, try to parse the date in ISO8601 date time format.
try {
return parseAsIso8601(sDate);
} catch (ParseException e) {
log.debug("tooLateExpireDate could not be parsed as an ISO8601 date: " + e.getMessage());
}
// Second, try to parse it as a hexadecimal value (without markers of any kind.. just a raw value).
if (tooLateExpireDate == null) {
try {
tooLateExpireDate = new Date(Long.parseLong(sDate, 16)*1000);
} catch (NumberFormatException e) {
log.debug("tooLateExpireDate could not be parsed as a hex value: " + e.getMessage());
}
}
}
if (tooLateExpireDate == null) {
log.debug("Using default value for ca.toolateexpiredate.");
tooLateExpireDate = new Date(Long.MAX_VALUE);
} else if (log.isDebugEnabled()) {
log.debug("tooLateExpireData is set to: "+tooLateExpireDate);
}
return tooLateExpireDate;
}
/**
* Rolls the given date one day forward or backward, until a date with a day not included in the restrictions (list of weekdays) is reached.
* @param date the date to change.
* @param restrictionsForWeekdays an array, { Calendar.SUNDAY, Calendar.MONDAY, etc}
* @param before roll back (or forward if false)
* @return the new date instance applied to the restrictions
* @throws IllegalArgumentException if given date or weekday restriction are null or all weekdays shall be excluded!
*/
public static Date applyExpirationRestrictionForWeekdays(final Date date, boolean[] restrictionsForWeekdays, boolean before) throws IllegalArgumentException {
if (null == date) {
throw new IllegalArgumentException("Date cannot be null!");
}
if (null == restrictionsForWeekdays) {
throw new IllegalArgumentException("Weekday restrictions cannot be null!");
}
boolean allDaysExcluded = true;
for (boolean enabled: restrictionsForWeekdays) {
if (!enabled) {
allDaysExcluded = false;
}
}
if (allDaysExcluded) {
throw new IllegalArgumentException("Weekday restrictions cannot be applied if all weekdays are excluded!");
}
final Calendar calendar = Calendar.getInstance();
calendar.setTime( date);
final int endDay = calendar.get(Calendar.DAY_OF_WEEK);
if (log.isDebugEnabled()) {
log.debug(">applyExpirationRestrictionForWeekdays for end date " + ValidityDate.formatAsISO8601ServerTZ( date.getTime(), ValidityDate.TIMEZONE_SERVER) + " with day " + endDay + " restrictions " + Arrays.toString(restrictionsForWeekdays));
}
if (restrictionsForWeekdays[endDay-1]) {
final int translation = before ? -1 : 1;
while(restrictionsForWeekdays[calendar.get(Calendar.DAY_OF_WEEK)-1]) {
calendar.add(Calendar.DAY_OF_MONTH, translation);
}
if (log.isDebugEnabled()) {
log.debug("Expiration restrictions for weekdays applied: Date changed from " + formatAsISO8601(date, TIMEZONE_SERVER) + " to " + formatAsISO8601(calendar.getTime(), TIMEZONE_SERVER));
}
return calendar.getTime();
}
return date;
}
}