org.ehcache.config.builders.UserManagedCacheBuilder Maven / Gradle / Ivy
Show all versions of ehcache-impl Show documentation
/*
* Copyright Terracotta, Inc.
*
* 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 org.ehcache.config.builders;
import org.ehcache.Cache;
import org.ehcache.CachePersistenceException;
import org.ehcache.UserManagedCache;
import org.ehcache.config.Builder;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.EvictionAdvisor;
import org.ehcache.config.ResourcePools;
import org.ehcache.config.ResourceType;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.core.Ehcache;
import org.ehcache.core.EhcacheWithLoaderWriter;
import org.ehcache.core.InternalCache;
import org.ehcache.core.PersistentUserManagedEhcache;
import org.ehcache.core.config.BaseCacheConfiguration;
import org.ehcache.core.config.ExpiryUtils;
import org.ehcache.core.events.CacheEventDispatcher;
import org.ehcache.core.events.CacheEventListenerConfiguration;
import org.ehcache.core.events.CacheEventListenerProvider;
import org.ehcache.core.internal.service.ServiceLocator;
import org.ehcache.core.internal.store.StoreConfigurationImpl;
import org.ehcache.core.internal.store.StoreSupport;
import org.ehcache.core.internal.util.ClassLoading;
import org.ehcache.core.resilience.DefaultRecoveryStore;
import org.ehcache.core.internal.resilience.RobustLoaderWriterResilienceStrategy;
import org.ehcache.core.internal.resilience.RobustResilienceStrategy;
import org.ehcache.core.spi.LifeCycled;
import org.ehcache.core.spi.LifeCycledAdapter;
import org.ehcache.core.spi.service.DiskResourceService;
import org.ehcache.core.spi.store.Store;
import org.ehcache.core.spi.store.heap.SizeOfEngine;
import org.ehcache.core.spi.store.heap.SizeOfEngineProvider;
import org.ehcache.event.CacheEventListener;
import org.ehcache.expiry.ExpiryPolicy;
import org.ehcache.impl.config.copy.DefaultCopierConfiguration;
import org.ehcache.impl.config.serializer.DefaultSerializerConfiguration;
import org.ehcache.impl.config.store.heap.DefaultSizeOfEngineProviderConfiguration;
import org.ehcache.impl.copy.SerializingCopier;
import org.ehcache.impl.events.CacheEventDispatcherImpl;
import org.ehcache.impl.internal.events.DisabledCacheEventNotificationService;
import org.ehcache.impl.internal.spi.event.DefaultCacheEventListenerProvider;
import org.ehcache.spi.copy.Copier;
import org.ehcache.spi.loaderwriter.CacheLoaderWriter;
import org.ehcache.spi.persistence.PersistableResourceService;
import org.ehcache.spi.resilience.ResilienceStrategy;
import org.ehcache.spi.serialization.SerializationProvider;
import org.ehcache.spi.serialization.Serializer;
import org.ehcache.spi.serialization.UnsupportedTypeException;
import org.ehcache.spi.service.Service;
import org.ehcache.spi.service.ServiceConfiguration;
import org.ehcache.spi.service.ServiceCreationConfiguration;
import org.ehcache.spi.service.ServiceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicLong;
import static org.ehcache.config.ResourceType.Core.DISK;
import static org.ehcache.config.ResourceType.Core.OFFHEAP;
import static org.ehcache.config.builders.ResourcePoolsBuilder.newResourcePoolsBuilder;
import static org.ehcache.core.internal.service.ServiceLocator.dependencySet;
import static org.ehcache.core.spi.service.ServiceUtils.findSingletonAmongst;
import static org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_MAX_OBJECT_SIZE;
import static org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_OBJECT_GRAPH_SIZE;
import static org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_UNIT;
/**
* The {@code UserManagedCacheBuilder} enables building {@link UserManagedCache}s using a fluent style.
*
* {@link UserManagedCache}s are {@link Cache}s that are not linked to a {@link org.ehcache.CacheManager}.
*
* As with all Ehcache builders, all instances are immutable and calling any method on the builder will return a new
* instance without modifying the one on which the method was called.
* This enables the sharing of builder instances without any risk of seeing them modified by code elsewhere.
*
* @param the cache key type
* @param the cache value type
* @param the specific {@code UserManagedCache} type
*/
public class UserManagedCacheBuilder> implements Builder {
private static final Logger LOGGER = LoggerFactory.getLogger(UserManagedCacheBuilder.class);
private static final AtomicLong instanceId = new AtomicLong(0L);
private final Class keyType;
private final Class valueType;
private String id;
private final Set services = new HashSet<>();
private final Set> serviceCreationConfigurations = new HashSet<>();
private ExpiryPolicy super K, ? super V> expiry = ExpiryPolicy.NO_EXPIRY;
private ClassLoader classLoader = ClassLoading.getDefaultClassLoader();
private EvictionAdvisor super K, ? super V> evictionAdvisor;
private CacheLoaderWriter super K, V> cacheLoaderWriter;
private CacheEventDispatcher eventDispatcher = new DisabledCacheEventNotificationService<>();
private ResourcePools resourcePools = newResourcePoolsBuilder().heap(Long.MAX_VALUE, EntryUnit.ENTRIES).build();
private Copier keyCopier;
private boolean useKeySerializingCopier;
private Copier valueCopier;
private boolean useValueSerializingCopier;
private Serializer keySerializer;
private Serializer valueSerializer;
private int dispatcherConcurrency = 4;
private List eventListenerConfigurations = new ArrayList<>();
private ExecutorService unOrderedExecutor;
private ExecutorService orderedExecutor;
private long objectGraphSize = DEFAULT_OBJECT_GRAPH_SIZE;
private long maxObjectSize = DEFAULT_MAX_OBJECT_SIZE;
private MemoryUnit sizeOfUnit = DEFAULT_UNIT;
UserManagedCacheBuilder(final Class keyType, final Class valueType) {
this.keyType = keyType;
this.valueType = valueType;
}
private UserManagedCacheBuilder(UserManagedCacheBuilder toCopy) {
this.keyType = toCopy.keyType;
this.valueType = toCopy.valueType;
this.id = toCopy.id;
this.services.addAll(toCopy.services);
this.serviceCreationConfigurations.addAll(toCopy.serviceCreationConfigurations);
this.expiry = toCopy.expiry;
this.classLoader = toCopy.classLoader;
this.evictionAdvisor = toCopy.evictionAdvisor;
this.cacheLoaderWriter = toCopy.cacheLoaderWriter;
this.eventDispatcher = toCopy.eventDispatcher;
this.resourcePools = toCopy.resourcePools;
this.keyCopier = toCopy.keyCopier;
this.valueCopier = toCopy.valueCopier;
this.keySerializer = toCopy.keySerializer;
this.valueSerializer = toCopy.valueSerializer;
this.useKeySerializingCopier = toCopy.useKeySerializingCopier;
this.useValueSerializingCopier = toCopy.useValueSerializingCopier;
this.eventListenerConfigurations = toCopy.eventListenerConfigurations;
this.unOrderedExecutor = toCopy.unOrderedExecutor;
this.orderedExecutor = toCopy.orderedExecutor;
this.objectGraphSize = toCopy.objectGraphSize;
this.maxObjectSize = toCopy.maxObjectSize;
this.sizeOfUnit = toCopy.sizeOfUnit;
}
T build(ServiceLocator.DependencySet serviceLocatorBuilder) throws IllegalStateException {
validateListenerConfig();
ServiceLocator serviceLocator;
try {
for (ServiceCreationConfiguration> serviceCreationConfig : serviceCreationConfigurations) {
serviceLocatorBuilder = serviceLocatorBuilder.with(serviceCreationConfig);
}
serviceLocatorBuilder = serviceLocatorBuilder.with(Store.Provider.class);
serviceLocator = serviceLocatorBuilder.build();
serviceLocator.startAllServices();
} catch (Exception e) {
throw new IllegalStateException("UserManagedCacheBuilder failed to build.", e);
}
List> serviceConfigsList = new ArrayList<>();
if (keyCopier != null) {
serviceConfigsList.add(new DefaultCopierConfiguration<>(keyCopier, DefaultCopierConfiguration.Type.KEY));
} else if (useKeySerializingCopier) {
serviceConfigsList.add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.KEY));
}
if (valueCopier != null) {
serviceConfigsList.add(new DefaultCopierConfiguration<>(valueCopier, DefaultCopierConfiguration.Type.VALUE));
} else if (useValueSerializingCopier) {
serviceConfigsList.add(new DefaultCopierConfiguration<>(SerializingCopier.asCopierClass(), DefaultCopierConfiguration.Type.VALUE));
}
CacheConfiguration cacheConfig = new BaseCacheConfiguration<>(keyType, valueType, evictionAdvisor,
classLoader, expiry, resourcePools);
List lifeCycledList = new ArrayList<>();
Set> resources = resourcePools.getResourceTypeSet();
boolean persistent = resources.contains(DISK);
if (persistent) {
if (id == null) {
throw new IllegalStateException("Persistent user managed caches must have an id set");
}
final DiskResourceService diskResourceService = serviceLocator.getService(DiskResourceService.class);
if (!resourcePools.getPoolForResource(ResourceType.Core.DISK).isPersistent()) {
try {
diskResourceService.destroy(id);
} catch (CachePersistenceException cpex) {
throw new RuntimeException("Unable to clean-up persistence space for non-restartable cache " + id, cpex);
}
}
try {
final PersistableResourceService.PersistenceSpaceIdentifier> identifier = diskResourceService.getPersistenceSpaceIdentifier(id, cacheConfig);
lifeCycledList.add(new LifeCycledAdapter() {
@Override
public void close() throws Exception {
diskResourceService.releasePersistenceSpaceIdentifier(identifier);
}
});
serviceConfigsList.add(identifier);
} catch (CachePersistenceException cpex) {
throw new RuntimeException("Unable to create persistence space for cache " + id, cpex);
}
}
Serializer keySerializer = this.keySerializer;
Serializer valueSerializer = this.valueSerializer;
if (keySerializer != null) {
serviceConfigsList.add(new DefaultSerializerConfiguration<>(this.keySerializer, DefaultSerializerConfiguration.Type.KEY));
}
if (valueSerializer != null) {
serviceConfigsList.add(new DefaultSerializerConfiguration<>(this.valueSerializer, DefaultSerializerConfiguration.Type.VALUE));
}
ServiceConfiguration>[] serviceConfigs = serviceConfigsList.toArray(new ServiceConfiguration>[0]);
final SerializationProvider serialization = serviceLocator.getService(SerializationProvider.class);
if (serialization != null) {
try {
if (keySerializer == null) {
final Serializer keySer = serialization.createKeySerializer(keyType, classLoader, serviceConfigs);
lifeCycledList.add(
new LifeCycledAdapter() {
@Override
public void close() throws Exception {
serialization.releaseSerializer(keySer);
}
}
);
keySerializer = keySer;
}
if (valueSerializer == null) {
final Serializer valueSer = serialization.createValueSerializer(valueType, classLoader, serviceConfigs);
lifeCycledList.add(
new LifeCycledAdapter() {
@Override
public void close() throws Exception {
serialization.releaseSerializer(valueSer);
}
}
);
valueSerializer = valueSer;
}
} catch (UnsupportedTypeException e) {
if (resources.contains(OFFHEAP) || resources.contains(DISK)) {
throw new RuntimeException(e);
} else {
LOGGER.debug("Serializers for cache '{}' failed creation ({}). However, depending on the configuration, they might not be needed", id, e.getMessage());
}
}
}
final Store.Provider storeProvider = StoreSupport.selectStoreProvider(serviceLocator, resources, serviceConfigsList);
Store.Configuration storeConfig = new StoreConfigurationImpl<>(keyType, valueType, evictionAdvisor, classLoader,
expiry, resourcePools, dispatcherConcurrency, keySerializer, valueSerializer);
final Store store = storeProvider.createStore(storeConfig, serviceConfigs);
lifeCycledList.add(new LifeCycled() {
@Override
public void init() {
storeProvider.initStore(store);
}
@Override
public void close() {
storeProvider.releaseStore(store);
}
});
if (this.eventDispatcher instanceof DisabledCacheEventNotificationService && (orderedExecutor != null & unOrderedExecutor != null)) {
this.eventDispatcher = new CacheEventDispatcherImpl<>(unOrderedExecutor, orderedExecutor);
}
eventDispatcher.setStoreEventSource(store.getStoreEventSource());
ResilienceStrategy resilienceStrategy;
if (cacheLoaderWriter == null) {
resilienceStrategy = new RobustResilienceStrategy<>(new DefaultRecoveryStore<>(store));
} else {
resilienceStrategy = new RobustLoaderWriterResilienceStrategy(new DefaultRecoveryStore<>(store), cacheLoaderWriter);
}
if (persistent) {
DiskResourceService diskResourceService = serviceLocator
.getService(DiskResourceService.class);
if (diskResourceService == null) {
throw new IllegalStateException("No LocalPersistenceService could be found - did you configure one?");
}
PersistentUserManagedEhcache cache = new PersistentUserManagedEhcache<>(cacheConfig, store, resilienceStrategy, diskResourceService, cacheLoaderWriter, eventDispatcher, id);
registerListeners(cache, serviceLocator, lifeCycledList);
for (LifeCycled lifeCycled : lifeCycledList) {
cache.addHook(lifeCycled);
}
return cast(cache);
} else {
final InternalCache cache;
if (cacheLoaderWriter == null) {
cache = new Ehcache<>(cacheConfig, store, resilienceStrategy, eventDispatcher, getLoggerFor(Ehcache.class));
} else {
cache = new EhcacheWithLoaderWriter<>(cacheConfig, store, resilienceStrategy, cacheLoaderWriter, eventDispatcher, getLoggerFor(EhcacheWithLoaderWriter.class));
}
registerListeners(cache, serviceLocator, lifeCycledList);
for (LifeCycled lifeCycled : lifeCycledList) {
(cache).addHook(lifeCycled);
}
return cast(cache);
}
}
private Logger getLoggerFor(Class> clazz) {
String loggerName;
if (id != null) {
loggerName = clazz.getName() + "-" + id;
} else {
loggerName = clazz.getName() + "-UserManaged" + instanceId.incrementAndGet();
}
return LoggerFactory.getLogger(loggerName);
}
private void validateListenerConfig() {
if (!eventListenerConfigurations.isEmpty() && eventDispatcher instanceof DisabledCacheEventNotificationService) {
if (orderedExecutor == null && unOrderedExecutor == null) {
throw new IllegalArgumentException("Listeners will not work unless Executors or EventDispatcher is configured.");
}
}
}
private void registerListeners(Cache cache, ServiceProvider serviceProvider, List lifeCycledList) {
if (!eventListenerConfigurations.isEmpty()) {
final CacheEventListenerProvider listenerProvider;
CacheEventListenerProvider provider;
if ((provider = serviceProvider.getService(CacheEventListenerProvider.class)) != null) {
listenerProvider = provider;
} else {
listenerProvider = new DefaultCacheEventListenerProvider();
}
for (CacheEventListenerConfiguration config : eventListenerConfigurations) {
final CacheEventListener listener = listenerProvider.createEventListener(id, config);
if (listener != null) {
cache.getRuntimeConfiguration().registerCacheEventListener(listener, config.orderingMode(), config.firingMode(), config.fireOn());
lifeCycledList.add(new LifeCycled() {
@Override
public void init() {
}
@Override
public void close() throws Exception {
listenerProvider.releaseEventListener(listener);
}
});
}
}
}
eventDispatcher.setListenerSource(cache);
}
@SuppressWarnings("unchecked")
T cast(UserManagedCache cache) {
return (T)cache;
}
/**
* Builds the {@link UserManagedCache}, initializing it if requested.
*
* @param init whether to initialize or not the cache before returning
* @return a user managed cache
* @throws IllegalStateException if the user managed cache cannot be built
*/
public final T build(final boolean init) throws IllegalStateException {
final T build = build(dependencySet().withoutMandatoryServices().with(services));
if (init) {
build.init();
}
return build;
}
/**
* Builds an unitialized {@link UserManagedCache}.
*
* @return an uninitialized user managed cache
*/
@Override
public T build() {
return build(false);
}
/**
* Specifies the returned {@link UserManagedCache} subtype through a specific {@link UserManagedCacheConfiguration}
* which will optionally add configurations to the returned builder.
*
* @param cfg the {@code UserManagedCacheConfiguration} to use
* @param the subtype of {@code UserManagedCache}
* @return a new builder ready to build a more specific subtype of user managed cache
*
* @see org.ehcache.PersistentUserManagedCache
* @see org.ehcache.impl.config.persistence.UserManagedPersistenceContext
*/
public final UserManagedCacheBuilder with(UserManagedCacheConfiguration cfg) {
return cfg.builder(this);
}
/**
* Adds an identifier to the returned builder.
*
* The identifier will be used in services and logging the way a cache alias would be inside a {@code CacheManager}
* @param identifier the identifier
* @return a new builder with the added identifier
*/
public final UserManagedCacheBuilder identifier(String identifier) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.id = identifier;
return otherBuilder;
}
/**
* Adds a {@link ClassLoader}, to load non Ehcache types, to the returned builder.
*
* @param classLoader the class loader to use
* @return a new builder with the added class loader
*/
public final UserManagedCacheBuilder withClassLoader(ClassLoader classLoader) {
if (classLoader == null) {
throw new NullPointerException("Null classloader");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.classLoader = classLoader;
return otherBuilder;
}
/**
* Adds {@link org.ehcache.expiry.Expiry} configuration to the returned builder.
*
* @param expiry the expiry to use
* @return a new builer with the added expiry
*
* @deprecated Use {@link #withExpiry(ExpiryPolicy)} instead
*/
@Deprecated
public final UserManagedCacheBuilder withExpiry(org.ehcache.expiry.Expiry super K, ? super V> expiry) {
if (expiry == null) {
throw new NullPointerException("Null expiry");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.expiry = ExpiryUtils.convertToExpiryPolicy(expiry);
return otherBuilder;
}
/**
* Adds {@link ExpiryPolicy} configuration to the returned builder.
*
* @param expiry the expiry to use
* @return a new builer with the added expiry
*/
public final UserManagedCacheBuilder withExpiry(ExpiryPolicy super K, ? super V> expiry) {
if (expiry == null) {
throw new NullPointerException("Null expiry");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.expiry = expiry;
return otherBuilder;
}
/**
* Adds an {@link CacheEventDispatcher} to the returned builder.
*
* This is one way of providing a mandatory part of supporting event listeners in {@link UserManagedCache}
*
* @param eventDispatcher the event dispatcher to use
* @return a new builder with the configured event dispatcher
*
* @see #withEventExecutors(ExecutorService, ExecutorService)
* @see #withEventListeners(CacheEventListenerConfiguration...)
* @see #withEventListeners(CacheEventListenerConfigurationBuilder)
*/
public final UserManagedCacheBuilder withEventDispatcher(CacheEventDispatcher eventDispatcher) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.orderedExecutor = null;
otherBuilder.unOrderedExecutor = null;
otherBuilder.eventDispatcher = eventDispatcher;
return otherBuilder;
}
/**
* Adds the default {@link CacheEventDispatcher} using the provided {@link ExecutorService} to the returned builder.
*
* This is one way of providing a mandatory part of supporting event listeners in {@link UserManagedCache}
*
* @param orderedExecutor the ordered event executor service
* @param unOrderedExecutor the unordered event executor service
* @return a new builder with the configured event dispatcher
*
* @see #withEventDispatcher(CacheEventDispatcher)
* @see #withEventListeners(CacheEventListenerConfiguration...)
* @see #withEventListeners(CacheEventListenerConfigurationBuilder)
*/
public final UserManagedCacheBuilder withEventExecutors(ExecutorService orderedExecutor, ExecutorService unOrderedExecutor) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.eventDispatcher = new DisabledCacheEventNotificationService<>();
otherBuilder.orderedExecutor = orderedExecutor;
otherBuilder.unOrderedExecutor = unOrderedExecutor;
return otherBuilder;
}
/**
* Convenience method to add a {@link CacheEventListenerConfiguration} based on the provided
* {@link CacheEventListenerConfigurationBuilder} to the returned builder.
*
* @param cacheEventListenerConfiguration the builder to get the configuration from
* @return a new builder with the added event listener configuration
*
* @see #withEventDispatcher(CacheEventDispatcher)
* @see #withEventExecutors(ExecutorService, ExecutorService)
* @see #withEventListeners(CacheEventListenerConfiguration...)
*/
public final UserManagedCacheBuilder withEventListeners(CacheEventListenerConfigurationBuilder cacheEventListenerConfiguration) {
return withEventListeners(cacheEventListenerConfiguration.build());
}
/**
* Adds one or more {@link CacheEventListenerConfiguration} to the returned builder.
*
* @param cacheEventListenerConfigurations the cache event listener configurations
* @return a new builders with the added event listener configurations
*
* @see #withEventDispatcher(CacheEventDispatcher)
* @see #withEventExecutors(ExecutorService, ExecutorService)
* @see #withEventListeners(CacheEventListenerConfigurationBuilder)
*/
public final UserManagedCacheBuilder withEventListeners(CacheEventListenerConfiguration... cacheEventListenerConfigurations) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.eventListenerConfigurations.addAll(Arrays.asList(cacheEventListenerConfigurations));
return otherBuilder;
}
/**
* Adds a {@link ResourcePools} configuration to the returned builder.
*
* @param resourcePools the resource pools to use
* @return a new builder with the configured resource pools
*
* @see #withResourcePools(ResourcePoolsBuilder)
*/
public final UserManagedCacheBuilder withResourcePools(ResourcePools resourcePools) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.resourcePools = resourcePools;
return otherBuilder;
}
/**
* Convenience method to add a {@link ResourcePools} configuration based on the provided {@link ResourcePoolsBuilder}
* to the returned builder.
*
* @param resourcePoolsBuilder the builder to get the resource pools from
* @return a new builder with the configured resource pools
*
* @see #withResourcePools(ResourcePools)
*/
public final UserManagedCacheBuilder withResourcePools(ResourcePoolsBuilder resourcePoolsBuilder) {
return withResourcePools(resourcePoolsBuilder.build());
}
/**
* Adds a configuration for dispatcher concurrency in event processing.
*
* @param dispatcherConcurrency the dispatcher concurrency level
* @return a new builder with the added configuration
*/
public final UserManagedCacheBuilder withDispatcherConcurrency(int dispatcherConcurrency) {
this.dispatcherConcurrency = dispatcherConcurrency;
return this;
}
/**
* Adds an {@link EvictionAdvisor} to the returned builder.
*
* @param evictionAdvisor the eviction advisor to use
* @return a new builder with the added eviction advisor
*/
public UserManagedCacheBuilder withEvictionAdvisor(EvictionAdvisor evictionAdvisor) {
if (evictionAdvisor == null) {
throw new NullPointerException("Null eviction advisor");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.evictionAdvisor = evictionAdvisor;
return otherBuilder;
}
/**
* Adds a {@link CacheLoaderWriter} to the returned builder.
*
* @param loaderWriter the cache loader writer to use
* @return a new builder with the added cache loader writer
*/
public UserManagedCacheBuilder withLoaderWriter(CacheLoaderWriter loaderWriter) {
if (loaderWriter == null) {
throw new NullPointerException("Null loaderWriter");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.cacheLoaderWriter = loaderWriter;
return otherBuilder;
}
/**
* Adds a configuration for {@link Copier key copying} using the key {@link Serializer} to the returned builder.
*
* @return a new builder with the added configuration
*
* @see #withKeyCopier(Copier)
* @see #withKeySerializer(Serializer)
*/
public UserManagedCacheBuilder withKeySerializingCopier() {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.keyCopier = null;
otherBuilder.useKeySerializingCopier = true;
return otherBuilder;
}
/**
* Adds a configuration for {@link Copier value copying} using the key {@link Serializer} to the returned builder.
*
* @return a new builder with the added configuration
*
* @see #withValueCopier(Copier)
* @see #withValueSerializer(Serializer)
*/
public UserManagedCacheBuilder withValueSerializingCopier() {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.valueCopier = null;
otherBuilder.useValueSerializingCopier = true;
return otherBuilder;
}
/**
* Adds a configuration for key {@link Copier} to the returned builder.
*
* @param keyCopier the key copier to use
* @return a new builder with the added key copier configuration
*
* @see #withKeySerializingCopier()
*/
public UserManagedCacheBuilder withKeyCopier(Copier keyCopier) {
if (keyCopier == null) {
throw new NullPointerException("Null key copier");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.keyCopier = keyCopier;
otherBuilder.useKeySerializingCopier = false;
return otherBuilder;
}
/**
* Adds a configuration for value {@link Copier} to the returned builder.
*
* @param valueCopier the value copier to use
* @return a new builder with the added value copier configuration
*
* @see #withValueSerializingCopier()
*/
public UserManagedCacheBuilder withValueCopier(Copier valueCopier) {
if (valueCopier == null) {
throw new NullPointerException("Null value copier");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.valueCopier = valueCopier;
otherBuilder.useValueSerializingCopier = false;
return otherBuilder;
}
/**
* Adds a configuration for key {@link Serializer} to the returned builder.
*
* @param keySerializer the key serializer to use
* @return a new builder with the added key serializer configuration
*/
public UserManagedCacheBuilder withKeySerializer(Serializer keySerializer) {
if (keySerializer == null) {
throw new NullPointerException("Null key serializer");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.keySerializer = keySerializer;
return otherBuilder;
}
/**
* Adds a configuration for value {@link Serializer} to the returned builder.
*
* @param valueSerializer the value serializer to use
* @return a new builder with the added value serializer configuration
*/
public UserManagedCacheBuilder withValueSerializer(Serializer valueSerializer) {
if (valueSerializer == null) {
throw new NullPointerException("Null value serializer");
}
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
otherBuilder.valueSerializer = valueSerializer;
return otherBuilder;
}
/**
* Adds or updates the {@link DefaultSizeOfEngineProviderConfiguration} with the specified object graph maximum size to the configured
* builder.
*
* {@link SizeOfEngine} is what enables the heap tier to be sized in {@link MemoryUnit}.
*
* @param size the maximum graph size
* @return a new builder with the added / updated configuration
*/
public UserManagedCacheBuilder withSizeOfMaxObjectGraph(long size) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
removeAnySizeOfEngine(otherBuilder);
otherBuilder.objectGraphSize = size;
otherBuilder.serviceCreationConfigurations.add(new DefaultSizeOfEngineProviderConfiguration(otherBuilder.maxObjectSize, otherBuilder.sizeOfUnit, otherBuilder.objectGraphSize));
return otherBuilder;
}
/**
* Adds or updates the {@link DefaultSizeOfEngineProviderConfiguration} with the specified maximum mapping size to the configured
* builder.
*
* {@link SizeOfEngine} is what enables the heap tier to be sized in {@link MemoryUnit}.
*
* @param size the maximum mapping size
* @param unit the memory unit
* @return a new builder with the added / updated configuration
*/
public UserManagedCacheBuilder withSizeOfMaxObjectSize(long size, MemoryUnit unit) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
removeAnySizeOfEngine(otherBuilder);
otherBuilder.maxObjectSize = size;
otherBuilder.sizeOfUnit = unit;
otherBuilder.serviceCreationConfigurations.add(new DefaultSizeOfEngineProviderConfiguration(otherBuilder.maxObjectSize, otherBuilder.sizeOfUnit, otherBuilder.objectGraphSize));
return otherBuilder;
}
/**
* Creates a new {@code UserManagedCacheBuilder}.
*
* @param keyType the cache key type
* @param valueType the cache value type
* @param the key type
* @param the value type
* @return the new builder
*/
public static UserManagedCacheBuilder> newUserManagedCacheBuilder(Class keyType, Class valueType) {
return new UserManagedCacheBuilder<>(keyType, valueType);
}
/**
* Adds a {@link Service} to be made available to the returned builder.
*
* Note that while {@link Service}s will be started upon {@link UserManagedCache} construction, no other lifecycle
* operations will be performed on them. It is the responsibility of the developer to properly stop
* {@code Service}s once they are no longer required.
*
* @param service the service to add
* @return a new builder with the added service
*
* @see #using(ServiceCreationConfiguration)
*/
public UserManagedCacheBuilder using(Service service) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
if (service instanceof SizeOfEngineProvider) {
removeAnySizeOfEngine(otherBuilder);
}
otherBuilder.services.add(service);
return otherBuilder;
}
/**
* Adds a {@link ServiceCreationConfiguration}, to trigger a service loading and its configuration, to the returned
* builder.
*
* Note that while {@link Service}s will be started upon {@link UserManagedCache} construction, no other lifecycle
* operations will be performed on them. It is the responsibility of the developer to properly stop
* {@code Service}s once they are no longer required. Which means that this method should not be used to get
* services that require a stop.
*
* @param serviceConfiguration the service creation configuration to add
* @return a new builder with the added service creation configuration
*
* @see #using(Service)
*/
public UserManagedCacheBuilder using(ServiceCreationConfiguration> serviceConfiguration) {
UserManagedCacheBuilder otherBuilder = new UserManagedCacheBuilder<>(this);
if (serviceConfiguration instanceof DefaultSizeOfEngineProviderConfiguration) {
removeAnySizeOfEngine(otherBuilder);
}
otherBuilder.serviceCreationConfigurations.add(serviceConfiguration);
return otherBuilder;
}
private static void removeAnySizeOfEngine(UserManagedCacheBuilder, ?, ?> builder) {
builder.services.remove(findSingletonAmongst(SizeOfEngineProvider.class, builder.services));
builder.serviceCreationConfigurations.remove(findSingletonAmongst(DefaultSizeOfEngineProviderConfiguration.class, builder.serviceCreationConfigurations));
}
}