org.ehcache.config.builders.CacheConfigurationBuilder Maven / Gradle / Ivy
Show all versions of ehcache 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.config.Builder;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.EvictionAdvisor;
import org.ehcache.config.FluentCacheConfigurationBuilder;
import org.ehcache.config.ResourcePools;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.impl.config.BaseCacheConfiguration;
import org.ehcache.core.config.store.StoreEventSourceConfiguration;
import org.ehcache.expiry.ExpiryPolicy;
import org.ehcache.impl.config.copy.DefaultCopierConfiguration;
import org.ehcache.impl.config.event.DefaultCacheEventDispatcherConfiguration;
import org.ehcache.impl.config.event.DefaultCacheEventListenerConfiguration;
import org.ehcache.impl.config.event.DefaultEventSourceConfiguration;
import org.ehcache.impl.config.loaderwriter.DefaultCacheLoaderWriterConfiguration;
import org.ehcache.impl.config.resilience.DefaultResilienceStrategyConfiguration;
import org.ehcache.impl.config.serializer.DefaultSerializerConfiguration;
import org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration;
import org.ehcache.impl.copy.SerializingCopier;
import org.ehcache.spi.copy.Copier;
import org.ehcache.spi.loaderwriter.CacheLoaderWriter;
import org.ehcache.spi.resilience.ResilienceStrategy;
import org.ehcache.spi.serialization.Serializer;
import org.ehcache.spi.service.ServiceConfiguration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static org.ehcache.core.config.ExpiryUtils.convertToExpiryPolicy;
/**
* The {@code CacheConfigurationBuilder} enables building {@link CacheConfiguration}s using a fluent style.
*
* 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.
*/
public class CacheConfigurationBuilder implements FluentCacheConfigurationBuilder> {
private final Collection> serviceConfigurations = new HashSet<>();
private ExpiryPolicy super K, ? super V> expiry;
private ClassLoader classLoader = null;
private EvictionAdvisor super K, ? super V> evictionAdvisor;
private ResourcePools resourcePools;
private final Class keyType;
private final Class valueType;
/**
* Creates a new instance ready to produce a {@link CacheConfiguration} with key type {@code } and with value type
* {@code } and which will use the {@link ResourcePools configured resources}.
*
* @param keyType the key type
* @param valueType the value type
* @param resourcePools the resources to use
* @param the key type
* @param the value type
* @return a {@code CacheConfigurationBuilder}
*/
public static CacheConfigurationBuilder newCacheConfigurationBuilder(Class keyType, Class valueType, ResourcePools resourcePools) {
return new CacheConfigurationBuilder<>(keyType, valueType, resourcePools);
}
/**
* Creates a new instance ready to produce a {@link CacheConfiguration} with key type {@code } and with value type
* {@code } and which will use the {@link ResourcePools configured resources}, passed as a {@link ResourcePoolsBuilder}.
*
* @param keyType the key type
* @param valueType the value type
* @param resourcePoolsBuilder the resources to use, as a builder
* @param the key type
* @param the value type
* @return a {@code CacheConfigurationBuilder}
*/
public static CacheConfigurationBuilder newCacheConfigurationBuilder(Class keyType, Class valueType, Builder extends ResourcePools> resourcePoolsBuilder) {
return new CacheConfigurationBuilder<>(keyType, valueType, resourcePoolsBuilder.build());
}
/**
* Creates a new instance ready to produce a {@link CacheConfiguration} functionally equivalent to the supplied configuration.
*
* @param configuration seed configuration
* @param the key type
* @param the value type
* @return a {@code CacheConfigurationBuilder}
*/
public static CacheConfigurationBuilder newCacheConfigurationBuilder(CacheConfiguration configuration) {
CacheConfigurationBuilder builder = newCacheConfigurationBuilder(configuration.getKeyType(), configuration.getValueType(), configuration.getResourcePools())
.withEvictionAdvisor(configuration.getEvictionAdvisor())
.withExpiry(configuration.getExpiryPolicy());
ClassLoader classLoader = configuration.getClassLoader();
if (classLoader != null) {
builder = builder.withClassLoader(classLoader);
}
for (ServiceConfiguration, ?> serviceConfig : configuration.getServiceConfigurations()) {
builder = builder.withService(serviceConfig);
}
return builder;
}
private CacheConfigurationBuilder(Class keyType, Class valueType, ResourcePools resourcePools) {
this.keyType = keyType;
this.valueType = valueType;
this.resourcePools = resourcePools;
}
private CacheConfigurationBuilder(CacheConfigurationBuilder other) {
this.keyType = other.keyType;
this.valueType = other.valueType;
this.expiry = other.expiry;
this.classLoader = other.classLoader;
this.evictionAdvisor = other.evictionAdvisor;
this.resourcePools = other.resourcePools;
this.serviceConfigurations.addAll(other.serviceConfigurations);
}
/**
* Adds a {@link ServiceConfiguration} to the returned builder.
*
* @param configuration the service configuration to add
* @return a new builder with the added service configuration
* @deprecated in favor of {@link #withService(ServiceConfiguration)}
*/
@Deprecated
public CacheConfigurationBuilder add(ServiceConfiguration, ?> configuration) {
if (!getServices(configuration.getClass()).isEmpty()) {
if (configuration instanceof DefaultCopierConfiguration>
|| configuration instanceof DefaultSerializerConfiguration>
|| configuration instanceof DefaultCacheEventListenerConfiguration) {
return withService(configuration);
} else {
throw new IllegalStateException("Cannot add a generic service configuration when another one already exists. " +
"Rely on specific with* methods or make sure your remove other configuration first.");
}
}
return withService(configuration);
}
/**
* Convenience method to add a {@link ServiceConfiguration} that is produced by a {@link Builder}.
*
* @param configurationBuilder the service configuration to add, {@link Builder#build()} will be called on it
* @return a new builder with the added service configuration
*
* @see #add(ServiceConfiguration)
* @deprecated in favor of {@link #withService(Builder)}
*/
@Deprecated
public CacheConfigurationBuilder add(Builder extends ServiceConfiguration, ?>> configurationBuilder) {
return add(configurationBuilder.build());
}
@Override
public > Collection getServices(Class configurationType) throws IllegalArgumentException {
return serviceConfigurations.stream().filter(configurationType::isInstance).map(configurationType::cast).collect(toList());
}
@Override
public CacheConfigurationBuilder withService(ServiceConfiguration, ?> config) {
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.serviceConfigurations.removeIf(other -> !other.compatibleWith(config) || !config.compatibleWith(other));
otherBuilder.serviceConfigurations.add(config);
return otherBuilder;
}
@Override
public CacheConfigurationBuilder withoutServices(Class extends ServiceConfiguration, ?>> clazz) {
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.serviceConfigurations.removeIf(clazz::isInstance);
return otherBuilder;
}
@Override
public >CacheConfigurationBuilder withoutServices(Class clazz, Predicate super C> predicate) {
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.serviceConfigurations.removeIf(c -> clazz.isInstance(c) && predicate.test(clazz.cast(c)));
return otherBuilder;
}
@Override
public > CacheConfigurationBuilder updateServices(Class clazz, UnaryOperator update) {
Collection extends ServiceConfiguration, R>> existing = getServices(clazz);
if (existing.isEmpty()) {
throw new IllegalStateException("Cannot update service configurations. No existing services of type: " + clazz);
} else {
CacheConfigurationBuilder otherBuilder = withoutServices(clazz);
for (ServiceConfiguration, R> configuration : existing) {
ServiceConfiguration, ?> replacement = configuration.build(update.apply(configuration.derive()));
if (replacement == null) {
throw new NullPointerException(configuration.getClass().getSimpleName() + ".build(...) returned a null configuration instance");
} else {
otherBuilder = otherBuilder.withService(replacement);
}
}
return otherBuilder;
}
}
@Override
public CacheConfigurationBuilder withEvictionAdvisor(final EvictionAdvisor super K, ? super V> evictionAdvisor) {
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.evictionAdvisor = evictionAdvisor;
return otherBuilder;
}
/**
* Removes a {@link ServiceConfiguration} from the returned builder.
*
* @param configuration the service configuration to remove
* @return a new builder without the specified configuration
* @deprecated in favor of {@link #withoutServices(Class)} or {@link #withoutServices(Class, Predicate)}
*/
@Deprecated
public CacheConfigurationBuilder remove(ServiceConfiguration, ?> configuration) {
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.serviceConfigurations.remove(configuration);
return otherBuilder;
}
/**
* Clears all {@link ServiceConfiguration}s from the returned builder.
*
* @return a new builder with no service configurations left
* @deprecated in favor of {@link #withoutServices(Class) withoutServices(ServiceConfiguration.class)}
*/
@Deprecated @SuppressWarnings("unchecked")
public CacheConfigurationBuilder clearAllServiceConfig() {
return withoutServices((Class) ServiceConfiguration.class);
}
/**
* Returns the first {@link ServiceConfiguration} with type matching the class passed in.
*
* @param clazz the service configuration class
* @param the type of the service configuration
* @return a matching service configuration, or {@code null} if none can be found
* @deprecated in favor of {@link #getService(Class)}
*/
@Deprecated
public > T getExistingServiceConfiguration(Class clazz) {
Iterator iterator = getServices(clazz).iterator();
return iterator.hasNext() ? iterator.next() : null;
}
/**
* Returns all {@link ServiceConfiguration}s of type matching the class passed in.
*
* @param clazz the service configuration class
* @param the type of the service configuration
* @return a list with service configurations
* @deprecated in favor of {@link #getServices(Class)}
*/
@Deprecated
public > List getExistingServiceConfigurations(Class clazz) {
return new ArrayList<>(getServices(clazz));
}
@Override
public CacheConfigurationBuilder withClassLoader(ClassLoader classLoader) {
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.classLoader = requireNonNull(classLoader);
return otherBuilder;
}
@Override
public CacheConfigurationBuilder withDefaultClassLoader() {
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.classLoader = null;
return otherBuilder;
}
@Override
public CacheConfigurationBuilder withResourcePools(ResourcePools resourcePools) {
if (resourcePools == null) {
throw new NullPointerException("Null resource pools");
}
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.resourcePools = resourcePools;
return otherBuilder;
}
@Override
public CacheConfigurationBuilder updateResourcePools(UnaryOperator update) {
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.resourcePools = update.apply(resourcePools);
return otherBuilder;
}
/**
* Adds {@link org.ehcache.expiry.Expiry} configuration to the returned builder.
*
* {@code Expiry} is what controls data freshness in a cache.
*
* @param expiry the expiry to use
* @return a new builder with the added expiry
*
* @deprecated Use {@link #withExpiry(ExpiryPolicy)} instead
*/
@Deprecated
public CacheConfigurationBuilder withExpiry(org.ehcache.expiry.Expiry super K, ? super V> expiry) {
return withExpiry(convertToExpiryPolicy(requireNonNull(expiry, "Null expiry")));
}
@Override
public CacheConfigurationBuilder withExpiry(ExpiryPolicy super K, ? super V> expiry) {
if (expiry == null) {
throw new NullPointerException("Null expiry");
}
CacheConfigurationBuilder otherBuilder = new CacheConfigurationBuilder<>(this);
otherBuilder.expiry = expiry;
return otherBuilder;
}
/**
* Indicates whether this builder has configured expiry or not.
*
* @return {@code true} if expiry configured, {@code false} otherwise
*/
public boolean hasConfiguredExpiry() {
return expiry != null;
}
@Override
public CacheConfigurationBuilder withLoaderWriter(CacheLoaderWriter loaderWriter) {
return withService(new DefaultCacheLoaderWriterConfiguration(requireNonNull(loaderWriter, "Null loaderWriter")));
}
@Override
public CacheConfigurationBuilder withLoaderWriter(Class> loaderWriterClass, Object... arguments) {
return withService(new DefaultCacheLoaderWriterConfiguration(requireNonNull(loaderWriterClass, "Null loaderWriterClass"), arguments));
}
@Override
public CacheConfigurationBuilder withoutLoaderWriter() {
return withoutServices(DefaultCacheLoaderWriterConfiguration.class);
}
@Override
public CacheConfigurationBuilder withResilienceStrategy(ResilienceStrategy resilienceStrategy) {
return withService(new DefaultResilienceStrategyConfiguration(requireNonNull(resilienceStrategy, "Null resilienceStrategy")));
}
@Override @SuppressWarnings("rawtypes")
public CacheConfigurationBuilder withResilienceStrategy(Class extends ResilienceStrategy> resilienceStrategyClass, Object... arguments) {
return withService(new DefaultResilienceStrategyConfiguration(requireNonNull(resilienceStrategyClass, "Null resilienceStrategyClass"), arguments));
}
@Override
public CacheConfigurationBuilder withDefaultResilienceStrategy() {
return withoutServices(DefaultResilienceStrategyConfiguration.class);
}
@Override
public CacheConfigurationBuilder withKeySerializingCopier() {
return withKeyCopier(SerializingCopier.asCopierClass());
}
@Override
public CacheConfigurationBuilder withValueSerializingCopier() {
return withValueCopier(SerializingCopier.asCopierClass());
}
@Override
public CacheConfigurationBuilder withKeyCopier(Copier keyCopier) {
return withService(new DefaultCopierConfiguration<>(requireNonNull(keyCopier, "Null key copier"), DefaultCopierConfiguration.Type.KEY));
}
@Override
public CacheConfigurationBuilder withKeyCopier(Class extends Copier> keyCopierClass) {
return withService(new DefaultCopierConfiguration<>(requireNonNull(keyCopierClass, "Null key copier class"), DefaultCopierConfiguration.Type.KEY));
}
@Override
public CacheConfigurationBuilder withoutKeyCopier() {
return withoutServices(DefaultCopierConfiguration.class, c -> DefaultCopierConfiguration.Type.KEY.equals(c.getType()));
}
@Override
public CacheConfigurationBuilder withValueCopier(Copier valueCopier) {
return withService(new DefaultCopierConfiguration<>(requireNonNull(valueCopier, "Null value copier"), DefaultCopierConfiguration.Type.VALUE));
}
@Override
public CacheConfigurationBuilder withValueCopier(Class extends Copier> valueCopierClass) {
return withService(new DefaultCopierConfiguration<>(requireNonNull(valueCopierClass, "Null value copier class"), DefaultCopierConfiguration.Type.VALUE));
}
@Override
public CacheConfigurationBuilder withoutValueCopier() {
return withoutServices(DefaultCopierConfiguration.class, c -> DefaultCopierConfiguration.Type.VALUE.equals(c.getType()));
}
@Override
public CacheConfigurationBuilder withKeySerializer(Serializer keySerializer) {
return withService(new DefaultSerializerConfiguration<>(requireNonNull(keySerializer, "Null key serializer"), DefaultSerializerConfiguration.Type.KEY));
}
@Override
public CacheConfigurationBuilder withKeySerializer(Class extends Serializer> keySerializerClass) {
return withService(new DefaultSerializerConfiguration<>(requireNonNull(keySerializerClass, "Null key serializer class"), DefaultSerializerConfiguration.Type.KEY));
}
@Override
public CacheConfigurationBuilder withDefaultKeySerializer() {
return withoutServices(DefaultSerializerConfiguration.class, config -> DefaultSerializerConfiguration.Type.KEY.equals(config.getType()));
}
@Override
public CacheConfigurationBuilder withValueSerializer(Serializer valueSerializer) {
return withService(new DefaultSerializerConfiguration<>(requireNonNull(valueSerializer, "Null value serializer"), DefaultSerializerConfiguration.Type.VALUE));
}
@Override
public CacheConfigurationBuilder withValueSerializer(Class extends Serializer> valueSerializerClass) {
return withService(new DefaultSerializerConfiguration<>(requireNonNull(valueSerializerClass, "Null value serializer class"), DefaultSerializerConfiguration.Type.VALUE));
}
@Override
public CacheConfigurationBuilder withDefaultValueSerializer() {
return withoutServices(DefaultSerializerConfiguration.class, config -> DefaultSerializerConfiguration.Type.VALUE.equals(config.getType()));
}
/**
* Adds {@link StoreEventSourceConfiguration} with the specified dispatcher concurrency
* to the configured builder.
*
* @param dispatcherConcurrency the level of concurrency in the dispatcher for ordered events
* @return a new builder with the added configuration
*
* @see #withDefaultDispatcherConcurrency()
*/
public CacheConfigurationBuilder withDispatcherConcurrency(int dispatcherConcurrency) {
return withService(new DefaultEventSourceConfiguration(dispatcherConcurrency));
}
/**
* Restores the default dispatcher concurrency.
*
* @return a new builder with the default dispatcher concurrency
*
* @see #withDispatcherConcurrency(int)
*/
public CacheConfigurationBuilder withDefaultDispatcherConcurrency() {
return withoutServices(DefaultEventSourceConfiguration.class);
}
/**
* Adds a {@link ServiceConfiguration} for the {@link org.ehcache.core.events.CacheEventDispatcherFactory} specifying
* the thread pool alias to use.
*
* @param threadPoolAlias the thread pool alias to use
* @return a new builder with the added configuration
*
* @see #withDefaultEventListenersThreadPool()
*/
public CacheConfigurationBuilder withEventListenersThreadPool(String threadPoolAlias) {
return withService(new DefaultCacheEventDispatcherConfiguration(threadPoolAlias));
}
/**
* Restores the default event listener thread pool settings.
*
* @return a new builder with the default event listener thread pool settings
*
* @see #withEventListenersThreadPool(String)
*/
public CacheConfigurationBuilder withDefaultEventListenersThreadPool() {
return withoutServices(DefaultCacheEventDispatcherConfiguration.class);
}
/**
* Adds a {@link ServiceConfiguration} for the {@link org.ehcache.impl.internal.store.disk.OffHeapDiskStore.Provider}
* indicating thread pool alias and write concurrency.
*
* @param threadPoolAlias the thread pool alias
* @param concurrency the write concurrency
* @return a new builder with the added configuration
*
* @see #withDefaultDiskStoreThreadPool()
*/
public CacheConfigurationBuilder withDiskStoreThreadPool(String threadPoolAlias, int concurrency) {
return installOrUpdate(
() -> new OffHeapDiskStoreConfiguration(threadPoolAlias, concurrency),
existing -> new OffHeapDiskStoreConfiguration(threadPoolAlias, concurrency, existing.getDiskSegments())
);
}
/**
* Restores the default disk store thread pool settings.
*
* @return a new builder with the default disk store thread pool settings
*
* @see #withDiskStoreThreadPool(String, int)
*/
public CacheConfigurationBuilder withDefaultDiskStoreThreadPool() {
return withoutServices(OffHeapDiskStoreConfiguration.class);
}
/**
* Adds or updates the {@link org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration} with the specified object graph maximum size to the configured
* builder.
*
* {@link org.ehcache.core.spi.store.heap.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
*
* @see #withSizeOfMaxObjectSize(long, MemoryUnit)
* @see #withDefaultSizeOfSettings()
*/
@Deprecated
public CacheConfigurationBuilder withSizeOfMaxObjectGraph(long size) {
return installOrUpdate(
() -> new org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration(org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_MAX_OBJECT_SIZE, org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_UNIT, size),
existing -> new org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration(existing.getMaxObjectSize(), existing.getUnit(), size)
);
}
/**
* Adds or updates the {@link org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration} with the specified maximum mapping size to the configured
* builder.
*
* {@link org.ehcache.core.spi.store.heap.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
*
* @see #withSizeOfMaxObjectGraph(long)
* @see #withDefaultSizeOfSettings()
*/
@Deprecated
public CacheConfigurationBuilder withSizeOfMaxObjectSize(long size, MemoryUnit unit) {
return installOrUpdate(
() -> new org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration(size, unit, org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.DEFAULT_OBJECT_GRAPH_SIZE),
existing -> new org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration(size, unit, existing.getMaxObjectGraphSize())
);
}
/**
* Restores the default size-of settings.
*
* @return a new builder with the default size-of settings
*
* @see #withSizeOfMaxObjectGraph(long)
* @see #withSizeOfMaxObjectSize(long, MemoryUnit)
*/
@Deprecated
public CacheConfigurationBuilder withDefaultSizeOfSettings() {
return withoutServices(org.ehcache.impl.config.store.heap.DefaultSizeOfEngineConfiguration.class);
}
@Override
public CacheConfiguration build() {
return new BaseCacheConfiguration<>(keyType, valueType, evictionAdvisor,
classLoader, expiry, resourcePools,
serviceConfigurations.toArray(new ServiceConfiguration, ?>[serviceConfigurations.size()]));
}
private > CacheConfigurationBuilder installOrUpdate(Supplier supplier, UnaryOperator update) {
C newConfig = supplier.get();
@SuppressWarnings("unchecked")
Class extends C> configType = (Class extends C>) newConfig.getClass();
if (getServices(configType).isEmpty()) {
return withService(newConfig);
} else {
return updateServices(configType, update);
}
}
}