All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.helidon.security.SecurityTime Maven / Gradle / Ivy

There is a newer version: 4.1.6
Show newest version
/*
 * Copyright (c) 2018, 2021 Oracle and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.helidon.security;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

import io.helidon.config.Config;
import io.helidon.config.metadata.Configured;
import io.helidon.config.metadata.ConfiguredOption;

/**
 * Time used in security, configurable.
 * Configuration may either shift time (to past or future) or explicitly set a value on one of the time fields (e.g. year, month)
 */
public class SecurityTime {
    private final long shiftSeconds;
    private final ZoneId timeZone;
    private final List chronoValues = new ArrayList<>();

    private SecurityTime(Builder builder) {
        this.shiftSeconds = builder.shiftBySeconds;
        this.timeZone = builder.timeZone;
        this.chronoValues.addAll(builder.values);
    }

    /**
     * A new builder for this class.
     *
     * @return builder to build a new instance
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Creates a new security time based on default time zone and current time.
     *
     * @return security time
     */
    public static SecurityTime create() {
        return SecurityTime.builder().build();
    }

    /**
     * Load an instance from configuration.
     * 

* Example: *

     * # server-time
     * server-time:
     *   # can shift time if needed (before explicit values are applied
     *   # shift-by-seconds: -1020
     *   #
     *   # All of the following settings:
     *   #   if configured, will override actual value, if not set, current value is used
     *   #
     *   # definition of a time zone (that is valid for ZoneId.of())
     *   # this will move the time to the specific timezone (same instant)
     *   # Time zone is applied first, everything else after
     *   # time-zone: Europe/Prague
     *   time-zone: "Australia/Darwin"
     *   year: 2017
     *   # 1 for January, 12 for December
     *   month: 9
     *   # day of month (1 - 31)
     *   day-of-month: 6
     *   # hour of day (0 - 23)
     *   hour-of-day: 13
     *   # minute of hour (0 - 59)
     *   minute: 0
     *   # second of minute (0-59)
     *   second: 0
     *   # millisecond of minute (0-999)
     *   # millisecond: 0
     * 
* * @param config configuration located on the key "server-time" in example above (the key name can differ, the content is * important) * @return a new instance of time configured from this configuration */ public static SecurityTime create(Config config) { return builder().config(config).build(); } /** * Get current (or as configured) time. * * @return a date time with a time-zone information as configured for this instance */ public ZonedDateTime get() { ZonedDateTime zdt = ZonedDateTime.now(); zdt = zdt.withZoneSameInstant(timeZone); zdt = zdt.plus(shiftSeconds, ChronoUnit.SECONDS); for (ChronoValues chronoValues : this.chronoValues) { zdt = zdt.with(chronoValues.field, chronoValues.value); } return zdt; } /** * Fluent API builder for {@link SecurityTime}. */ @Configured public static final class Builder implements io.helidon.common.Builder { private final List values = new ArrayList<>(); private ZoneId timeZone = ZoneId.systemDefault(); private long shiftBySeconds = 0; private Builder() { } @Override public SecurityTime build() { return new SecurityTime(this); } /** * Override current time zone. The time will represent the SAME instant, in an explicit timezone. *

* If we are in a UTC time zone and you set the timezone to "Europe/Prague", the time will be shifted by the offset * of Prague (e.g. if it is noon right now in UTC, you would get 14:00). * * @param zoneId zone id to use for the instance being built * @return updated builder instance */ @ConfiguredOption public Builder timeZone(ZoneId zoneId) { this.timeZone = zoneId; return this; } /** * Configure a time-shift in seconds, to move the current time to past or future. * * @param seconds number of seconds by which we want to shift the system time, may be negative * @return updated builder instance */ @ConfiguredOption("0") public Builder shiftBySeconds(long seconds) { this.shiftBySeconds = seconds; return this; } /** * Set an explicit value for one of the time fields (such as {@link ChronoField#YEAR}). * * @param field field to set * @param value value to set on the field, see javadoc of each field to see possible values * @return updated builder instance */ @ConfiguredOption(key = "year", type = Long.class) @ConfiguredOption(key = "month", type = Long.class) @ConfiguredOption(key = "day-of-month", type = Long.class) @ConfiguredOption(key = "hour-of-day", type = Long.class) @ConfiguredOption(key = "minute", type = Long.class) @ConfiguredOption(key = "second", type = Long.class) @ConfiguredOption(key = "millisecond", type = Long.class) public Builder value(ChronoField field, long value) { this.values.add(new ChronoValues(field, value)); return this; } /** * Update this builder from configuration. The config should be located on parent key of the following keys * (all of them are optional): *

    *
  • time-zone: set time zone id (such as Europe/Prague) of desired time zone
  • *
  • shift-by-seconds: {@link #shiftBySeconds(long)}
  • *
  • year: set an explicit year value
  • *
  • month: set an explicit month value (1-12)
  • *
  • day-of-month: set an explicit day of month value (1-31)
  • *
  • hour-of-day: set an explicit hour of day value (0-23)
  • *
  • minute: set an explicit minute value (0-59)
  • *
  • second: set an explicit second value (0-59)
  • *
  • millisecond: set an explicit millisecond value (0-999)
  • *
* * @param config configuration to read data from * @return updated builder instance */ public Builder config(Config config) { // modification, time flows as usual config.get("time-zone").asString().map(ZoneId::of).ifPresent(this::timeZone); config.get("shift-by-seconds").asLong().ifPresent(this::shiftBySeconds); // explicit values, specific value is fixed in time config.get("year").asLong().ifPresent(it -> value(ChronoField.YEAR, it)); config.get("month").asLong().ifPresent(it -> value(ChronoField.MONTH_OF_YEAR, it)); config.get("day-of-month").asLong().ifPresent(it -> value(ChronoField.DAY_OF_MONTH, it)); config.get("hour-of-day").asLong().ifPresent(it -> value(ChronoField.HOUR_OF_DAY, it)); config.get("minute").asLong().ifPresent(it -> value(ChronoField.MINUTE_OF_HOUR, it)); config.get("second").asLong().ifPresent(it -> value(ChronoField.SECOND_OF_MINUTE, it)); config.get("millisecond").asLong().ifPresent(it -> value(ChronoField.MILLI_OF_SECOND, it)); return this; } } private static final class ChronoValues { private final ChronoField field; private final long value; private ChronoValues(ChronoField field, long delta) { this.field = field; this.value = delta; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy