001/**
002 * Copyright (C) 2006-2025 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.components.vault.jcache;
017
018import java.util.Iterator;
019import java.util.concurrent.CopyOnWriteArrayList;
020import java.util.function.Consumer;
021
022import javax.cache.Cache;
023import javax.cache.event.CacheEntryCreatedListener;
024import javax.cache.event.CacheEntryEvent;
025import javax.cache.event.CacheEntryExpiredListener;
026import javax.cache.event.CacheEntryListenerException;
027import javax.cache.event.CacheEntryRemovedListener;
028
029import lombok.RequiredArgsConstructor;
030
031@RequiredArgsConstructor
032public class CacheSizeManager<K, V> implements CacheEntryCreatedListener<K, V>, CacheEntryExpiredListener<K, V>,
033        CacheEntryRemovedListener<K, V>, Consumer<Cache<K, V>> {
034
035    private final int maxCacheSize;
036
037    private Cache<K, V> cache;
038
039    private final CopyOnWriteArrayList<K> keys = new CopyOnWriteArrayList<>();
040
041    @Override
042    public void onCreated(final Iterable<CacheEntryEvent<? extends K, ? extends V>> cacheEntryEvents)
043            throws CacheEntryListenerException {
044        cacheEntryEvents.forEach(it -> keys.add(it.getKey()));
045        if (keys.size() > maxCacheSize) {
046            final Iterator<K> iterator = keys.iterator();
047            synchronized (this) {
048                while (keys.size() > maxCacheSize && iterator.hasNext()) {
049                    cache.remove(iterator.next());
050                    iterator.remove();
051                }
052            }
053        }
054    }
055
056    @Override
057    public void onExpired(final Iterable<CacheEntryEvent<? extends K, ? extends V>> cacheEntryEvents)
058            throws CacheEntryListenerException {
059        onRemoved(cacheEntryEvents);
060    }
061
062    @Override
063    public void onRemoved(final Iterable<CacheEntryEvent<? extends K, ? extends V>> cacheEntryEvents)
064            throws CacheEntryListenerException {
065        cacheEntryEvents.forEach(it -> keys.remove(it.getKey()));
066    }
067
068    @Override
069    public void accept(final Cache<K, V> cache) {
070        this.cache = cache;
071    }
072}