001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * 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 distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.jose.jwk.source;
019
020
021import java.util.Date;
022import java.util.concurrent.TimeUnit;
023
024import com.nimbusds.jose.jwk.JWKSet;
025
026
027/**
028 * JSON Web Key (JWK) set cache implementation.
029 *
030 * @author Vladimir Dzhuvinov
031 * @version 2018-12-01
032 */
033public class DefaultJWKSetCache implements JWKSetCache {
034        
035        
036        /**
037         * The default lifespan for cached JWK sets (5 minutes).
038         */
039        public static final long DEFAULT_LIFESPAN_MINUTES = 5;
040        
041        
042        /**
043         * The lifespan the cached JWK set, in {@link #timeUnit}s, negative
044         * means no expiration
045         */
046        private final long lifespan;
047        
048        
049        /**
050         * The lifespan time unit, may be {@code null} if no expiration.
051         */
052        private final TimeUnit timeUnit;
053        
054        
055        /**
056         * The cache put timestamp, negative if not specified.
057         */
058        private long putTimestamp = -1;
059        
060        
061        /**
062         * Creates a new JWK set, the default lifespan of the cached JWK set is
063         * set to 5 minutes.
064         */
065        public DefaultJWKSetCache() {
066                
067                this(DEFAULT_LIFESPAN_MINUTES, TimeUnit.MINUTES);
068        }
069        
070        
071        /**
072         * Creates a new JWK set cache.
073         *
074         * @param lifespan The lifespan of the cached JWK set before it
075         *                 expires, negative means no expiration.
076         * @param timeUnit The lifespan time unit, may be {@code null} if no
077         *                 expiration.
078         */
079        public DefaultJWKSetCache(final long lifespan, final TimeUnit timeUnit) {
080                
081                this.lifespan = lifespan;
082                
083                if (lifespan > -1 && timeUnit == null) {
084                        throw new IllegalArgumentException("A time unit must be specified for non-negative lifespans");
085                }
086                
087                this.timeUnit = timeUnit;
088        }
089        
090        
091        /**
092         * The cached JWK set, {@code null} if none.
093         */
094        private JWKSet jwkSet;
095        
096        
097        @Override
098        public void put(final JWKSet jwkSet) {
099                
100                this.jwkSet = jwkSet;
101                
102                if (jwkSet != null) {
103                        putTimestamp = new Date().getTime();
104                } else {
105                        // cache cleared
106                        putTimestamp = -1;
107                }
108        }
109        
110        
111        @Override
112        public JWKSet get() {
113                
114                if (isExpired()) {
115                        jwkSet = null; // clear
116                }
117                
118                return jwkSet;
119        }
120        
121        
122        /**
123         * Returns the cache put timestamp.
124         *
125         * @return The cache put timestamp, negative if not specified.
126         */
127        public long getPutTimestamp() {
128                
129                return putTimestamp;
130        }
131        
132        
133        /**
134         * Returns {@code true} if the cached JWK set is expired.
135         *
136         * @return {@code true} if expired.
137         */
138        public boolean isExpired() {
139        
140                return putTimestamp > -1 &&
141                        lifespan > -1 &&
142                        new Date().getTime() > putTimestamp + TimeUnit.MILLISECONDS.convert(lifespan, timeUnit);
143        }
144        
145        
146        /**
147         * Returns the configured lifespan of the cached JWK.
148         *
149         * @param timeUnit The time unit to use.
150         *
151         * @return The configured lifespan, negative means no expiration.
152         */
153        public long getLifespan(final TimeUnit timeUnit) {
154                
155                if (lifespan < 0) {
156                        return lifespan;
157                }
158                
159                return timeUnit.convert(lifespan, timeUnit);
160        }
161}