@Test public void testStoreByValue() { CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build(false); cacheManager.init(); DefaultCopierConfiguration<String> copierConfiguration = new DefaultCopierConfiguration(SerializingCopier.class, CopierConfiguration.Type.VALUE); final Cache<Long, String> cache1 = cacheManager.createCache( "cache1", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class) .withResourcePools( ResourcePoolsBuilder.newResourcePoolsBuilder().heap(1, EntryUnit.ENTRIES)) .build()); performAssertions(cache1, true); final Cache<Long, String> cache2 = cacheManager.createCache( "cache2", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class) .add(copierConfiguration) .build()); performAssertions(cache2, false); final Cache<Long, String> cache3 = cacheManager.createCache( "cache3", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class) .build()); performAssertions(cache3, true); cacheManager.close(); }
@Test public void testUsingEhcacheConfiguration() throws Exception { // tag::ehcacheBasedConfigurationExample[] CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder() .buildConfig(Long.class, String.class); // <1> Cache<Long, String> cache = cacheManager.createCache( "myCache", Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration)); // <2> Eh107Configuration<Long, String> configuration = cache.getConfiguration(Eh107Configuration.class); configuration.unwrap(CacheConfiguration.class); // <3> configuration.unwrap(CacheRuntimeConfiguration.class); // <4> try { cache.getConfiguration(CompleteConfiguration.class); // <5> throw new AssertionError("IllegalArgumentException expected"); } catch (IllegalArgumentException iaex) { // Expected } // end::ehcacheBasedConfigurationExample[] }
@Test public void testCacheConfigUsage() { Set<EventType> eventTypeSet = new HashSet<EventType>(); eventTypeSet.add(EventType.CREATED); eventTypeSet.add(EventType.UPDATED); CacheEventListenerConfigurationBuilder listenerBuilder = CacheEventListenerConfigurationBuilder.newEventListenerConfiguration( ListenerObject.class, eventTypeSet) .unordered() .asynchronous(); final CacheManager manager = CacheManagerBuilder.newCacheManagerBuilder() .withCache( "foo", CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class) .add(listenerBuilder) .build()) .build(true); final Collection<?> bar = manager .getCache("foo", Object.class, Object.class) .getRuntimeConfiguration() .getServiceConfigurations(); assertThat(bar.iterator().next().getClass().toString(), is(ListenerObject.object.toString())); }
@Test public void testAddingCacheEventListenerConfigurationAtCacheLevel() { CacheManagerBuilder<CacheManager> cacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder(); CacheEventListenerConfiguration cacheEventListenerConfiguration = CacheEventListenerConfigurationBuilder.newEventListenerConfiguration( ListenerObject.class, EventType.CREATED) .unordered() .asynchronous() .build(); CacheManager cacheManager = cacheManagerBuilder.build(true); final Cache<Long, String> cache = cacheManager.createCache( "cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class) .add(cacheEventListenerConfiguration) .withResourcePools( ResourcePoolsBuilder.newResourcePoolsBuilder() .heap(100, EntryUnit.ENTRIES) .build()) .build()); Collection<ServiceConfiguration<?>> serviceConfiguration = cache.getRuntimeConfiguration().getServiceConfigurations(); assertThat( serviceConfiguration, IsCollectionContaining.<ServiceConfiguration<?>>hasItem( instanceOf(DefaultCacheEventListenerConfiguration.class))); cacheManager.close(); }
@Test public void testCanGetContext() { CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder() .withResourcePools( ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build()) .buildConfig(Long.class, String.class); ManagementRegistry managementRegistry = new DefaultManagementRegistry( new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCM")); CacheManager cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() .withCache("aCache", cacheConfiguration) .using(managementRegistry) .build(true); assertThat(managementRegistry.getContext().getName(), equalTo("cacheManagerName")); assertThat(managementRegistry.getContext().getValue(), equalTo("myCM")); assertThat(managementRegistry.getContext().getSubContexts(), hasSize(1)); assertThat( managementRegistry.getContext().getSubContexts().iterator().next().getName(), equalTo("cacheName")); assertThat( managementRegistry.getContext().getSubContexts().iterator().next().getValue(), equalTo("aCache")); cacheManager1.close(); }
@Before public void init() { CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder() .withResourcePools( ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build()) .buildConfig(Long.class, String.class); service = new DefaultSharedManagementService(); cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() .withCache("aCache1", cacheConfiguration) .using(service) .using(new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCM1")) .build(true); cacheManager2 = CacheManagerBuilder.newCacheManagerBuilder() .withCache("aCache2", cacheConfiguration) .withCache("aCache3", cacheConfiguration) .using(service) .using(new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCM2")) .build(true); // this serie of calls make sure the registry still works after a full init / close / init loop cacheManager1.close(); cacheManager1.init(); cacheManager2.close(); cacheManager2.init(); }
@Test public void testCall() { List<Context> contextList = Arrays.asList( Context.create().with("cacheManagerName", "myCM1").with("cacheName", "aCache1"), Context.create().with("cacheManagerName", "myCM1").with("cacheName", "aCache4"), Context.create().with("cacheManagerName", "myCM2").with("cacheName", "aCache2"), Context.create().with("cacheManagerName", "myCM55").with("cacheName", "aCache55")); cacheManager1.getCache("aCache1", Long.class, String.class).put(1L, "1"); cacheManager2.getCache("aCache2", Long.class, String.class).put(2L, "2"); assertThat(cacheManager1.getCache("aCache1", Long.class, String.class).get(1L), equalTo("1")); assertThat(cacheManager2.getCache("aCache2", Long.class, String.class).get(2L), equalTo("2")); CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder() .withResourcePools( ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build()) .buildConfig(Long.class, String.class); cacheManager1.createCache("aCache4", cacheConfiguration); cacheManager1.getCache("aCache4", Long.class, String.class).put(4L, "4"); assertThat(cacheManager1.getCache("aCache4", Long.class, String.class).get(4L), equalTo("4")); ResultSet<ContextualReturn<Void>> results = service.withCapability("ActionsCapability").call("clear").on(contextList).build().execute(); assertThat(results.size(), Matchers.equalTo(4)); assertThat(results.getResult(contextList.get(0)).hasValue(), is(true)); assertThat(results.getResult(contextList.get(1)).hasValue(), is(true)); assertThat(results.getResult(contextList.get(2)).hasValue(), is(true)); assertThat(results.getResult(contextList.get(3)).hasValue(), is(false)); assertThat(results.getResult(contextList.get(0)).getValue(), is(nullValue())); assertThat(results.getResult(contextList.get(1)).getValue(), is(nullValue())); assertThat(results.getResult(contextList.get(2)).getValue(), is(nullValue())); try { results.getResult(contextList.get(3)).getValue(); fail(); } catch (Exception e) { assertThat(e, instanceOf(NoSuchElementException.class)); } assertThat( cacheManager1.getCache("aCache1", Long.class, String.class).get(1L), is(Matchers.nullValue())); assertThat( cacheManager2.getCache("aCache2", Long.class, String.class).get(2L), is(Matchers.nullValue())); assertThat( cacheManager1.getCache("aCache4", Long.class, String.class).get(4L), is(Matchers.nullValue())); }
@Test public void testCanGetStats() { CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder() .withResourcePools( ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build()) .buildConfig(Long.class, String.class); ManagementRegistry managementRegistry = new DefaultManagementRegistry( new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCM")); CacheManager cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() .withCache("aCache1", cacheConfiguration) .withCache("aCache2", cacheConfiguration) .using(managementRegistry) .build(true); Map<String, String> context1 = new HashMap<String, String>(); context1.put("cacheManagerName", "myCM"); context1.put("cacheName", "aCache1"); Map<String, String> context2 = new HashMap<String, String>(); context2.put("cacheManagerName", "myCM"); context2.put("cacheName", "aCache2"); cacheManager1.getCache("aCache1", Long.class, String.class).put(1L, "1"); cacheManager1.getCache("aCache1", Long.class, String.class).put(2L, "2"); cacheManager1.getCache("aCache2", Long.class, String.class).put(3L, "3"); cacheManager1.getCache("aCache2", Long.class, String.class).put(4L, "4"); cacheManager1.getCache("aCache2", Long.class, String.class).put(5L, "5"); Collection<Counter> counters = managementRegistry.collectStatistics(context1, "StatisticsCapability", "PutCounter"); assertThat(counters, hasSize(1)); assertThat(counters.iterator().next().getValue(), equalTo(2L)); List<Collection<Counter>> allCounters = managementRegistry.collectStatistics( Arrays.asList(context1, context2), "StatisticsCapability", "PutCounter"); assertThat(allCounters, hasSize(2)); assertThat(allCounters.get(0), hasSize(1)); assertThat(allCounters.get(1), hasSize(1)); assertThat(allCounters.get(0).iterator().next().getValue(), equalTo(2L)); assertThat(allCounters.get(1).iterator().next().getValue(), equalTo(3L)); cacheManager1.close(); }
private Cache<String, Object> getCacheForGroupOrCreateIt(String group) { Cache<String, Object> cache = cacheManager.getCache(group, String.class, Object.class); if (cache == null) { synchronized (lock) { cache = cacheManager.getCache(group, String.class, Object.class); if (cache == null) { cache = cacheManager.createCache( group, cacheTemplate.buildConfig(String.class, Object.class)); } } } return cache; }
@Test public void testCanGetCapabilities() { CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder() .withResourcePools( ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build()) .buildConfig(Long.class, String.class); ManagementRegistry managementRegistry = new DefaultManagementRegistry( new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCM")); CacheManager cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() .withCache("aCache", cacheConfiguration) .using(managementRegistry) .build(true); assertThat(managementRegistry.getCapabilities(), hasSize(2)); assertThat( new ArrayList<Capability>(managementRegistry.getCapabilities()).get(0).getName(), equalTo("ActionsCapability")); assertThat( new ArrayList<Capability>(managementRegistry.getCapabilities()).get(1).getName(), equalTo("StatisticsCapability")); assertThat( new ArrayList<Capability>(managementRegistry.getCapabilities()).get(0).getDescriptions(), hasSize(4)); assertThat( new ArrayList<Capability>(managementRegistry.getCapabilities()).get(1).getDescriptions(), hasSize(16)); assertThat( new ArrayList<Capability>(managementRegistry.getCapabilities()) .get(0) .getCapabilityContext() .getAttributes(), hasSize(2)); assertThat( new ArrayList<Capability>(managementRegistry.getCapabilities()) .get(1) .getCapabilityContext() .getAttributes(), hasSize(2)); cacheManager1.close(); }
@Test public void testCall() { CacheConfiguration<Long, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder() .withResourcePools( ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES).build()) .buildConfig(Long.class, String.class); ManagementRegistry managementRegistry = new DefaultManagementRegistry( new DefaultManagementRegistryConfiguration().setCacheManagerAlias("myCM")); CacheManager cacheManager1 = CacheManagerBuilder.newCacheManagerBuilder() .withCache("aCache1", cacheConfiguration) .withCache("aCache2", cacheConfiguration) .using(managementRegistry) .build(true); Map<String, String> context = new HashMap<String, String>() { { put("cacheManagerName", "myCM"); put("cacheName", "aCache1"); } }; cacheManager1.getCache("aCache1", Long.class, String.class).put(1L, "1"); assertThat(cacheManager1.getCache("aCache1", Long.class, String.class).get(1L), equalTo("1")); Object result = managementRegistry.callAction( context, "ActionsCapability", "clear", new String[0], new Object[0]); assertThat(result, is(nullValue())); assertThat( cacheManager1.getCache("aCache1", Long.class, String.class).get(1L), is(Matchers.nullValue())); }
/** * Provides testing of basic CRUD operations on an {@code Ehcache}. * * @author Clifford W. Johnson */ public abstract class EhcacheBasicCrudBase { protected static final CacheConfiguration<String, String> CACHE_CONFIGURATION = CacheConfigurationBuilder.newCacheConfigurationBuilder() .buildConfig(String.class, String.class); @Mock protected Store<String, String> store; /** * Holds a {@link org.mockito.Mockito#spy(Object)}-wrapped reference to the {@link * org.ehcache.resilience.ResilienceStrategy ResilienceStrategy} used in the {@link * org.ehcache.Ehcache Ehcache} instance being tested. * * @see #setResilienceStrategySpy(Ehcache) */ protected ResilienceStrategy<String, String> spiedResilienceStrategy; @Before public void initMocks() { MockitoAnnotations.initMocks(this); } /** * Validates expected {@link org.terracotta.statistics.OperationStatistic} updates for the * indicated {@code Ehcache} instance. The statistics identified in {@code changed} are checked * for a value of {@code 1}; all other statistics in the same enumeration class are checked for a * value of {@code 0}. * * @param ehcache the {@code Ehcache} instance to check * @param changed the statistics values that should have updated values * @param <E> the statistics enumeration type */ protected static <E extends Enum<E>> void validateStats( final Ehcache<?, ?> ehcache, final EnumSet<E> changed) { assert changed != null; final EnumSet<E> unchanged = EnumSet.complementOf(changed); @SuppressWarnings("unchecked") final List<EnumSet<E>> sets = Arrays.asList(changed, unchanged); Class<E> statsClass = null; for (final EnumSet<E> set : sets) { if (!set.isEmpty()) { statsClass = set.iterator().next().getDeclaringClass(); break; } } assert statsClass != null; final OperationStatistic<E> operationStatistic = getOperationStatistic(ehcache, statsClass); for (final E statId : changed) { assertThat( String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), getStatistic(operationStatistic, statId), StatisticMatcher.equalTo(1L)); } for (final E statId : unchanged) { assertThat( String.format("Value for %s.%s", statId.getDeclaringClass().getName(), statId.name()), getStatistic(operationStatistic, statId), StatisticMatcher.equalTo(0L)); } } /** * Gets a reference to the {@link org.terracotta.statistics.OperationStatistic} instance holding * the class of statistics specified for the {@code Ehcache} instance provided. * * @param ehcache the {@code Ehcache} instance for which the {@code OperationStatistic} instance * should be obtained * @param statsClass the {@code Class} of statistics for which the {@code OperationStatistic} * instance should be obtained * @param <E> the {@code Enum} type for the statistics * @return a reference to the {@code OperationStatistic} instance holding the {@code statsClass} * statistics; may be {@code null} if {@code statsClass} statistics do not exist for {@code * ehcache} */ private static <E extends Enum<E>> OperationStatistic<E> getOperationStatistic( final Ehcache<?, ?> ehcache, final Class<E> statsClass) { for (final TreeNode statNode : ContextManager.nodeFor(ehcache).getChildren()) { final Object statObj = statNode.getContext().attributes().get("this"); if (statObj instanceof OperationStatistic<?>) { @SuppressWarnings("unchecked") final OperationStatistic<E> statistic = (OperationStatistic<E>) statObj; if (statistic.type().equals(statsClass)) { return statistic; } } } return null; } /** * Gets the value of the statistic indicated from an {@link * org.terracotta.statistics.OperationStatistic} instance. * * @param operationStatistic the {@code OperationStatistic} instance from which the statistic is * to be obtained * @param statId the {@code Enum} constant identifying the statistic for which the value must be * obtained * @param <E> The {@code Enum} type for the statistics * @return the value, possibly null, for {@code statId} about {@code ehcache} */ private static <E extends Enum<E>> Number getStatistic( final OperationStatistic<E> operationStatistic, final E statId) { if (operationStatistic != null) { final ValueStatistic<Long> valueStatistic = operationStatistic.statistic(statId); return (valueStatistic == null ? null : valueStatistic.value()); } return null; } /** * Returns a Mockito {@code any} Matcher for {@link org.ehcache.function.Function}. * * @return a Mockito {@code any} matcher for {@code Function}. */ @SuppressWarnings("unchecked") protected static Function<? super String, ? extends String> getAnyFunction() { return any(Function.class); // unchecked } /** * Returns a Mockito {@code any} Matcher for {@link org.ehcache.function.BiFunction}. * * @return a Mockito {@code any} matcher for {@code BiFunction}. */ @SuppressWarnings("unchecked") protected static BiFunction<? super String, String, String> getAnyBiFunction() { return any(BiFunction.class); // unchecked } /** * Returns a Mockito {@code any} Matcher for {@link NullaryFunction NullaryFunction<Boolean>}. * * @return a Mockito {@code any} matcher for {@code NullaryFunction}. */ @SuppressWarnings("unchecked") protected static NullaryFunction<Boolean> getBooleanNullaryFunction() { return any(NullaryFunction.class); // unchecked } /** * Replaces the {@link org.ehcache.resilience.ResilienceStrategy ResilienceStrategy} instance in * the {@link org.ehcache.Ehcache Ehcache} instance provided with a {@link * org.mockito.Mockito#spy(Object) Mockito <code>spy</code>} wrapping the original {@code * ResilienceStrategy} instance. * * @param ehcache the {@code Ehcache} instance to alter * @return the <code>spy</code>-wrapped {@code ResilienceStrategy} instance */ protected final <K, V> ResilienceStrategy<K, V> setResilienceStrategySpy( final Ehcache<K, V> ehcache) { assert ehcache != null; try { final Field resilienceStrategyField = ehcache.getClass().getDeclaredField("resilienceStrategy"); resilienceStrategyField.setAccessible(true); @SuppressWarnings("unchecked") ResilienceStrategy<K, V> resilienceStrategy = (ResilienceStrategy<K, V>) resilienceStrategyField.get(ehcache); if (resilienceStrategy != null) { resilienceStrategy = spy(resilienceStrategy); resilienceStrategyField.set(ehcache, resilienceStrategy); } return resilienceStrategy; } catch (Exception e) { throw new AssertionError( String.format("Unable to wrap ResilienceStrategy in Ehcache instance: %s", e)); } } /** * Provides a basic {@link org.ehcache.spi.cache.Store} implementation for testing. The contract * implemented by this {@code Store} is not strictly conformant but should be sufficient for * {@code Ehcache} implementation testing. */ // TODO: Use a validated Store implementation. protected static class FakeStore implements Store<String, String> { private final CacheConfigurationChangeListener cacheConfigurationChangeListener = new CacheConfigurationChangeListener() { @Override public void cacheConfigurationChange(CacheConfigurationChangeEvent event) { // noop } }; private static final NullaryFunction<Boolean> REPLACE_EQUAL_TRUE = new NullaryFunction<Boolean>() { @Override public Boolean apply() { return true; } }; /** The key:value pairs served by this {@code Store}. This map may be empty. */ private final Map<String, FakeValueHolder> entries; /** Keys for which access results in a thrown {@code Exception}. This set may be empty. */ private final Set<String> failingKeys; public FakeStore(final Map<String, String> entries) { this(entries, Collections.<String>emptySet()); } public FakeStore(final Map<String, String> entries, final Set<String> failingKeys) { assert failingKeys != null; // Use of ConcurrentHashMap is required to avoid ConcurrentModificationExceptions using // Iterator.remove this.entries = new ConcurrentHashMap<String, FakeValueHolder>(); if (entries != null) { for (final Map.Entry<String, String> entry : entries.entrySet()) { this.entries.put(entry.getKey(), new FakeValueHolder(entry.getValue())); } } this.failingKeys = Collections.unmodifiableSet(new HashSet<String>(failingKeys)); } /** * Gets a mapping of the entries in this {@code Store}. * * @return a new, unmodifiable map of the entries in this {@code Store}. */ protected Map<String, String> getEntryMap() { final Map<String, String> result = new HashMap<String, String>(); for (final Map.Entry<String, FakeValueHolder> entry : this.entries.entrySet()) { result.put(entry.getKey(), entry.getValue().value()); } return Collections.unmodifiableMap(result); } @Override public ValueHolder<String> get(final String key) throws CacheAccessException { this.checkFailingKey(key); final FakeValueHolder valueHolder = this.entries.get(key); if (valueHolder != null) { valueHolder.lastAccessTime = System.currentTimeMillis(); } return valueHolder; } @Override public boolean containsKey(final String key) throws CacheAccessException { this.checkFailingKey(key); return this.entries.containsKey(key); } @Override public void put(final String key, final String value) throws CacheAccessException { this.checkFailingKey(key); this.entries.put(key, new FakeValueHolder(value)); } @Override public ValueHolder<String> putIfAbsent(final String key, final String value) throws CacheAccessException { this.checkFailingKey(key); final FakeValueHolder currentValue = this.entries.get(key); if (currentValue == null) { this.entries.put(key, new FakeValueHolder(value)); return null; } currentValue.lastAccessTime = System.currentTimeMillis(); return currentValue; } @Override public void remove(final String key) throws CacheAccessException { this.checkFailingKey(key); this.entries.remove(key); } @Override public boolean remove(final String key, final String value) throws CacheAccessException { this.checkFailingKey(key); final ValueHolder<String> currentValue = this.entries.get(key); if (currentValue == null || !currentValue.value().equals(value)) { return false; } this.entries.remove(key); return true; } @Override public ValueHolder<String> replace(final String key, final String value) throws CacheAccessException { this.checkFailingKey(key); final ValueHolder<String> currentValue = this.entries.get(key); if (currentValue != null) { this.entries.put(key, new FakeValueHolder(value)); } return currentValue; } @Override public boolean replace(final String key, final String oldValue, final String newValue) throws CacheAccessException { this.checkFailingKey(key); final ValueHolder<String> currentValue = this.entries.get(key); if (currentValue != null && currentValue.value().equals(oldValue)) { this.entries.put(key, new FakeValueHolder(newValue)); return true; } return false; } @Override public void clear() throws CacheAccessException { this.entries.clear(); } @Override public void enableStoreEventNotifications(final StoreEventListener<String, String> listener) { // no-op } @Override public void disableStoreEventNotifications() { throw new UnsupportedOperationException(); } /** * {@inheritDoc} * * <p>The {@code Iterator} returned by this method <b>does not</b> have a {@code remove} method. * The {@code Iterator} returned by {@code FakeStore.this.entries.entrySet().iterator()} must * not throw {@link java.util.ConcurrentModificationException ConcurrentModification}. */ @Override public Iterator<Cache.Entry<String, ValueHolder<String>>> iterator() throws CacheAccessException { return new Iterator<Cache.Entry<String, ValueHolder<String>>>() { final java.util.Iterator<Map.Entry<String, FakeValueHolder>> iterator = FakeStore.this.entries.entrySet().iterator(); @Override public boolean hasNext() throws CacheAccessException { return this.iterator.hasNext(); } @Override public Cache.Entry<String, ValueHolder<String>> next() throws CacheAccessException { final Map.Entry<String, FakeValueHolder> cacheEntry = this.iterator.next(); FakeStore.this.checkFailingKey(cacheEntry.getKey()); cacheEntry.getValue().lastAccessTime = System.currentTimeMillis(); return new Cache.Entry<String, ValueHolder<String>>() { @Override public String getKey() { return cacheEntry.getKey(); } @Override public ValueHolder<String> getValue() { return cacheEntry.getValue(); } @Override public long getCreationTime(final TimeUnit unit) { return cacheEntry.getValue().creationTime(unit); } @Override public long getLastAccessTime(final TimeUnit unit) { return cacheEntry.getValue().lastAccessTime(unit); } @Override public float getHitRate(final TimeUnit unit) { return cacheEntry.getValue().hitRate(System.currentTimeMillis(), unit); } }; } }; } /** * {@inheritDoc} * * <p>This method is implemented as <code> * this.{@link #compute(String, BiFunction, NullaryFunction) compute}(keys, mappingFunction, () -> { returns true; }) * </code> */ @Override public ValueHolder<String> compute( final String key, final BiFunction<? super String, ? super String, ? extends String> mappingFunction) throws CacheAccessException { return this.compute(key, mappingFunction, REPLACE_EQUAL_TRUE); } /** * Common core for the {@link #compute(String, BiFunction, NullaryFunction)} and {@link * #computeIfPresent(String, BiFunction, NullaryFunction)} methods. * * @param key the key of the entry to process * @param currentValue the existing value, if any, for {@code key} * @param mappingFunction the function that will produce the value. The function will be * supplied with the key and existing value (or null if no entry exists) as parameters. The * function should return the desired new value for the entry or null to remove the entry. * If the method throws an unchecked exception the Store will not be modified (the caller * will receive the exception) * @param replaceEqual If the existing value in the store is {@link * java.lang.Object#equals(Object)} to the value returned from the mappingFunction this * function will be invoked. If this function returns {@link java.lang.Boolean#FALSE} then * the existing entry in the store will not be replaced with a new entry and the existing * entry will have its access time updated * @return the new value associated with the key or null if none */ private FakeValueHolder computeInternal( final String key, final FakeValueHolder currentValue, final BiFunction<? super String, ? super String, ? extends String> mappingFunction, final NullaryFunction<Boolean> replaceEqual) { final String remappedValue = mappingFunction.apply(key, (currentValue == null ? null : currentValue.value())); FakeValueHolder newValue = (remappedValue == null ? null : new FakeValueHolder(remappedValue)); if (newValue == null) { /* Remove entry from store */ this.entries.remove(key); } else if (!newValue.equals(currentValue)) { /* New, remapped value is different */ this.entries.put(key, newValue); } else { /* New, remapped value is the same */ if (replaceEqual.apply()) { /* Replace existing equal value */ this.entries.put(key, newValue); } else { /* Update access time of current entry */ currentValue.lastAccessTime = System.currentTimeMillis(); newValue = currentValue; } } return newValue; } @Override public ValueHolder<String> compute( final String key, final BiFunction<? super String, ? super String, ? extends String> mappingFunction, final NullaryFunction<Boolean> replaceEqual) throws CacheAccessException { this.checkFailingKey(key); return this.computeInternal(key, this.entries.get(key), mappingFunction, replaceEqual); } @Override public ValueHolder<String> computeIfAbsent( final String key, final Function<? super String, ? extends String> mappingFunction) throws CacheAccessException { this.checkFailingKey(key); FakeValueHolder currentValue = this.entries.get(key); if (currentValue == null) { final String newValue = mappingFunction.apply(key); if (newValue != null) { final FakeValueHolder newValueHolder = new FakeValueHolder(newValue); this.entries.put(key, newValueHolder); currentValue = newValueHolder; } } else { currentValue.lastAccessTime = System.currentTimeMillis(); } return currentValue; } @Override public ValueHolder<String> computeIfPresent( final String key, final BiFunction<? super String, ? super String, ? extends String> remappingFunction) throws CacheAccessException { return this.computeIfPresent(key, remappingFunction, REPLACE_EQUAL_TRUE); } @Override public ValueHolder<String> computeIfPresent( final String key, final BiFunction<? super String, ? super String, ? extends String> remappingFunction, final NullaryFunction<Boolean> replaceEqual) throws CacheAccessException { this.checkFailingKey(key); final FakeValueHolder currentValue = this.entries.get(key); if (currentValue == null) { return null; } return this.computeInternal(key, this.entries.get(key), remappingFunction, replaceEqual); } /** * {@inheritDoc} * * <p>This method is implemented as <code> * this.{@link #bulkCompute(Set, Function, NullaryFunction) * bulkCompute}(keys, remappingFunction, () -> { returns true; })</code> */ @Override public Map<String, ValueHolder<String>> bulkCompute( final Set<? extends String> keys, final Function< Iterable<? extends Map.Entry<? extends String, ? extends String>>, Iterable<? extends Map.Entry<? extends String, ? extends String>>> remappingFunction) throws CacheAccessException { return this.bulkCompute(keys, remappingFunction, REPLACE_EQUAL_TRUE); } /** * {@inheritDoc} * * <p>This implementation calls {@link #compute(String, BiFunction, NullaryFunction) * compute(key, BiFunction, replaceEqual)} for each key presented in {@code keys}. */ @Override public Map<String, org.ehcache.spi.cache.Store.ValueHolder<String>> bulkCompute( final Set<? extends String> keys, final Function< Iterable<? extends Entry<? extends String, ? extends String>>, Iterable<? extends Entry<? extends String, ? extends String>>> remappingFunction, final NullaryFunction<Boolean> replaceEqual) throws CacheAccessException { final Map<String, ValueHolder<String>> resultMap = new LinkedHashMap<String, ValueHolder<String>>(); for (final String key : keys) { final ValueHolder<String> newValue = this.compute( key, new BiFunction<String, String, String>() { @Override public String apply(final String key, final String oldValue) { final Entry<String, String> entry = new AbstractMap.SimpleEntry<String, String>(key, oldValue); final Entry<? extends String, ? extends String> remappedEntry = remappingFunction.apply(Collections.singletonList(entry)).iterator().next(); return remappedEntry.getValue(); } }, replaceEqual); resultMap.put(key, newValue); } return resultMap; } /** * {@inheritDoc} * * <p>This implementation is based, in part, on the implementation found in {@code * org.ehcache.internal.store.OnHeapStore}. This implementation calls {@code mappingFunction} * for each key through an internal function supplied to {@link #computeIfAbsent(String, * org.ehcache.function.Function) computeIfAbsent}. */ @Override public Map<String, ValueHolder<String>> bulkComputeIfAbsent( final Set<? extends String> keys, final Function< Iterable<? extends String>, Iterable<? extends Map.Entry<? extends String, ? extends String>>> mappingFunction) throws CacheAccessException { final Map<String, ValueHolder<String>> resultMap = new LinkedHashMap<String, ValueHolder<String>>(); for (final String key : keys) { final ValueHolder<String> newValue = this.computeIfAbsent( key, new Function<String, String>() { @Override public String apply(final String key) { final Map.Entry<? extends String, ? extends String> entry = mappingFunction.apply(Collections.singleton(key)).iterator().next(); return entry.getValue(); } }); resultMap.put(key, newValue); } return resultMap; } @Override public List<CacheConfigurationChangeListener> getConfigurationChangeListeners() { List<CacheConfigurationChangeListener> configurationChangeListenerList = new ArrayList<CacheConfigurationChangeListener>(); configurationChangeListenerList.add(this.cacheConfigurationChangeListener); return configurationChangeListenerList; } private void checkFailingKey(final String key) throws CacheAccessException { if (this.failingKeys.contains(key)) { throw new CacheAccessException(String.format("Accessing failing key: %s", key)); } } /** * A {@link org.ehcache.spi.cache.Store.ValueHolder} implementation for use within {@link * org.ehcache.EhcacheBasicCrudBase.FakeStore}. */ private static class FakeValueHolder implements ValueHolder<String> { private final String value; private final long creationTime; private long lastAccessTime; public FakeValueHolder(final String value) { this.value = value; this.creationTime = System.currentTimeMillis(); } @Override public String value() { return this.value; } @Override public long creationTime(final TimeUnit unit) { return unit.convert(this.creationTime, TimeUnit.MICROSECONDS); } @Override public long expirationTime(TimeUnit unit) { return 0; } @Override public boolean isExpired(long expirationTime, TimeUnit unit) { return false; } @Override public long lastAccessTime(final TimeUnit unit) { return unit.convert(this.lastAccessTime, TimeUnit.MICROSECONDS); } @Override public float hitRate(long now, final TimeUnit unit) { return 0; } @Override public long hits() { return 0; } @Override public long getId() { throw new UnsupportedOperationException("Implement me!"); } @Override public String toString() { return "FakeValueHolder{" + "value='" + this.value + '\'' + ", creationTime=" + this.creationTime + ", lastAccessTime=" + this.lastAccessTime + '}'; } } } /** * Local {@code org.hamcrest.TypeSafeMatcher} implementation for testing {@code * org.terracotta.statistics.OperationStatistic} values. */ private static final class StatisticMatcher extends TypeSafeMatcher<Number> { final Number expected; private StatisticMatcher(final Class<?> expectedType, final Number expected) { super(expectedType); this.expected = expected; } @Override protected boolean matchesSafely(final Number value) { if (value != null) { return (value.longValue() == this.expected.longValue()); } else { return this.expected.longValue() == 0L; } } @Override public void describeTo(final Description description) { if (this.expected.longValue() == 0L) { description.appendText("zero or null"); } else { description.appendValue(this.expected); } } @Factory public static Matcher<Number> equalTo(final Number expected) { return new StatisticMatcher(Number.class, expected); } } /** * Provides a basic {@link CacheLoaderWriter} implementation for testing. The contract implemented * by this {@code CacheLoaderWriter} may not be strictly conformant but should be sufficient for * {@code Ehcache} implementation testing. */ protected static class FakeCacheLoaderWriter implements CacheLoaderWriter<String, String> { private final Map<String, String> entries = new HashMap<String, String>(); /** Keys for which access results in a thrown {@code Exception}. This set may be empty. */ private final Set<String> failingKeys; private boolean isBulkCacheLoadingExceptionEnabled = false; /** * The entry key causing the {@link #writeAll(Iterable)} and {@link #deleteAll(Iterable)} * methods to fail by throwing an exception <i>other</i> than a {@link * org.ehcache.exceptions.BulkCacheWritingException BulkCacheWritingException}. * * @see #setCompleteFailureKey */ private volatile String completeFailureKey = null; public FakeCacheLoaderWriter(final Map<String, String> entries) { this(entries, Collections.<String>emptySet()); } public FakeCacheLoaderWriter(final Map<String, String> entries, final Set<String> failingKeys) { if (entries != null) { this.entries.putAll(entries); } this.failingKeys = (failingKeys.isEmpty() ? Collections.<String>emptySet() : Collections.unmodifiableSet(new HashSet<String>(failingKeys))); } public FakeCacheLoaderWriter( final Map<String, String> entries, final Set<String> failingKeys, boolean isBulkCacheLoadingExceptionEnabled) { this(entries, failingKeys); this.isBulkCacheLoadingExceptionEnabled = isBulkCacheLoadingExceptionEnabled; } Map<String, String> getEntryMap() { return Collections.unmodifiableMap(this.entries); } /** * Sets the key causing the {@link #writeAll(Iterable)} and {@link #deleteAll(Iterable)} methods * to throw an exception <i>other</i> that a {@link * org.ehcache.exceptions.BulkCacheWritingException BulkCacheWritingException}. * * <p>If a complete failure is recognized, the cache image maintained by this instance is in an * inconsistent state. * * @param completeFailureKey the key, which when processed by {@code writeAll} or {@code * deleteAll}, causes a complete failure of the method */ final void setCompleteFailureKey(final String completeFailureKey) { this.completeFailureKey = completeFailureKey; } @Override public void write(final String key, final String value) throws Exception { this.checkFailingKey(key); this.entries.put(key, value); } /** * {@inheritDoc} * * <p>If this method throws an exception <i>other</i> than a {@link * org.ehcache.exceptions.BulkCacheWritingException BulkCacheWritingException}, the cache image * maintained by this {@code CacheLoaderWriter} is in an inconsistent state. */ @Override public void writeAll( final Iterable<? extends Map.Entry<? extends String, ? extends String>> entries) throws Exception { final Set<String> successes = new LinkedHashSet<String>(); final Map<String, Exception> failures = new LinkedHashMap<String, Exception>(); for (final Entry<? extends String, ? extends String> entry : entries) { final String key = entry.getKey(); if (key.equals(this.completeFailureKey)) { throw new CompleteFailureException(); } try { this.write(key, entry.getValue()); successes.add(key); } catch (Exception e) { //noinspection ThrowableResultOfMethodCallIgnored failures.put(key, e); } } if (!failures.isEmpty()) { throw new BulkCacheWritingException(failures, successes); } } @Override public void delete(final String key) throws Exception { this.checkFailingKey(key); this.entries.remove(key); } /** * {@inheritDoc} * * <p>If this method throws an exception <i>other</i> than a {@link * org.ehcache.exceptions.BulkCacheWritingException BulkCacheWritingException}, the cache image * maintained by this {@code CacheLoaderWriter} is in an inconsistent state. */ @Override public void deleteAll(final Iterable<? extends String> keys) throws Exception { final Set<String> successes = new LinkedHashSet<String>(); final Map<String, Exception> failures = new LinkedHashMap<String, Exception>(); for (final String key : keys) { if (key.equals(this.completeFailureKey)) { throw new CompleteFailureException(); } try { this.delete(key); successes.add(key); } catch (Exception e) { //noinspection ThrowableResultOfMethodCallIgnored failures.put(key, e); } } if (!failures.isEmpty()) { throw new BulkCacheWritingException(failures, successes); } } private void checkFailingKey(final String key) throws FailedKeyException { if (this.failingKeys.contains(key)) { throw new FailedKeyException(String.format("Accessing failing key: %s", key)); } } private static final class CompleteFailureException extends Exception { private static final long serialVersionUID = -8796858843677614631L; public CompleteFailureException() {} } @Override public String load(final String key) throws Exception { if (this.failingKeys.contains(key)) { throw new FailedKeyException(key); } return this.entries.get(key); } @Override public Map<String, String> loadAll(final Iterable<? extends String> keys) throws Exception { if (isBulkCacheLoadingExceptionEnabled) { Map<String, Exception> failures = new HashMap<String, Exception>(); Map<String, String> loadedKeys = new HashMap<String, String>(); Exception loadingException = new RuntimeException("Exception loading keys"); for (String key : keys) { if (failingKeys.contains(key)) { failures.put(key, loadingException); } else { loadedKeys.put(key, null); } } throw new BulkCacheLoadingException(failures, loadedKeys); } final Map<String, String> resultMap = new HashMap<String, String>(); for (final String key : keys) { if (this.failingKeys.contains(key)) { throw new FailedKeyException(key); } resultMap.put(key, this.entries.get(key)); } return resultMap; } private static final class FailedKeyException extends Exception { private static final long serialVersionUID = 1085055801147786691L; public FailedKeyException(final String message) { super(message); } } } }
/** * Creates a new {@link org.ehcache.config.CacheConfigurationBuilder} seeded with the * cache-template configuration by the given {@code name} in the XML configuration parsed using * {@link #parseConfiguration()} * * @param name the unique name identifying the cache-template element in the XML * @param keyType the type of keys for the {@link org.ehcache.config.CacheConfigurationBuilder} to * use, would need to match the {@code key-type} declared in the template if declared in XML * @param valueType the type of values for the {@link * org.ehcache.config.CacheConfigurationBuilder} to use, would need to match the {@code * value-type} declared in the template if declared in XML * @param <K> type of keys * @param <V> type of values * @return the preconfigured {@link org.ehcache.config.CacheConfigurationBuilder} or {@code null} * if no cache-template for the provided {@code name} * @throws IllegalStateException if {@link #parseConfiguration()} hasn't yet been successfully * invoked * @throws IllegalArgumentException if {@code keyType} or {@code valueType} don't match the * declared type(s) of the template * @throws ClassNotFoundException if a {@link java.lang.Class} declared in the XML couldn't be * found * @throws InstantiationException if a user provided {@link java.lang.Class} couldn't get * instantiated * @throws IllegalAccessException if a method (including constructor) couldn't be invoked on a * user provided type */ @SuppressWarnings("unchecked") public <K, V> CacheConfigurationBuilder<K, V> newCacheConfigurationBuilderFromTemplate( final String name, final Class<K> keyType, final Class<V> valueType) throws InstantiationException, IllegalAccessException, ClassNotFoundException { final ConfigurationParser.CacheTemplate cacheTemplate = templates.get(name); if (cacheTemplate == null) { return null; } final ClassLoader defaultClassLoader = ClassLoading.getDefaultClassLoader(); Class keyClass = getClassForName(cacheTemplate.keyType(), defaultClassLoader); Class valueClass = getClassForName(cacheTemplate.valueType(), defaultClassLoader); if (keyType != null && cacheTemplate.keyType() != null && !keyClass.isAssignableFrom(keyType)) { throw new IllegalArgumentException( "CacheTemplate '" + name + "' declares key type of " + cacheTemplate.keyType()); } if (valueType != null && cacheTemplate.valueType() != null && !valueClass.isAssignableFrom(valueType)) { throw new IllegalArgumentException( "CacheTemplate '" + name + "' declares value type of " + cacheTemplate.valueType()); } CacheConfigurationBuilder<K, V> builder = CacheConfigurationBuilder.newCacheConfigurationBuilder(); builder = builder .usingEvictionPrioritizer( getInstanceOfName( cacheTemplate.evictionPrioritizer(), defaultClassLoader, EvictionPrioritizer.class, Eviction.Prioritizer.class)) .evictionVeto( getInstanceOfName( cacheTemplate.evictionVeto(), defaultClassLoader, EvictionVeto.class)); final ConfigurationParser.Expiry parsedExpiry = cacheTemplate.expiry(); if (parsedExpiry != null) { builder = builder.withExpiry(getExpiry(defaultClassLoader, parsedExpiry)); } if (cacheTemplate.keySerializer() != null) { final Class<Serializer<?>> keySerializer = (Class<Serializer<?>>) getClassForName(cacheTemplate.keySerializer(), defaultClassLoader); builder = builder.add( new DefaultSerializerConfiguration( keySerializer, DefaultSerializerConfiguration.Type.KEY)); } if (cacheTemplate.valueSerializer() != null) { final Class<Serializer<?>> valueSerializer = (Class<Serializer<?>>) getClassForName(cacheTemplate.valueSerializer(), defaultClassLoader); builder = builder.add( new DefaultSerializerConfiguration( valueSerializer, DefaultSerializerConfiguration.Type.VALUE)); } final String loaderWriter = cacheTemplate.loaderWriter(); if (loaderWriter != null) { final Class<CacheLoaderWriter<?, ?>> cacheLoaderWriterClass = (Class<CacheLoaderWriter<?, ?>>) getClassForName(loaderWriter, defaultClassLoader); builder = builder.add(new DefaultCacheLoaderWriterConfiguration(cacheLoaderWriterClass)); if (cacheTemplate.writeBehind() != null) { WriteBehind writeBehind = cacheTemplate.writeBehind(); WriteBehindConfigurationBuilder writeBehindConfigurationBuilder = WriteBehindConfigurationBuilder.newWriteBehindConfiguration() .concurrencyLevel(writeBehind.concurrency()) .queueSize(writeBehind.maxQueueSize()) .rateLimit(writeBehind.rateLimitPerSecond()) .retry(writeBehind.retryAttempts(), writeBehind.retryAttemptsDelay()) .delay(writeBehind.minWriteDelay(), writeBehind.maxWriteDelay()); if (writeBehind.isBatched()) { writeBehindConfigurationBuilder = writeBehindConfigurationBuilder.batchSize(writeBehind.batchSize()); } if (writeBehind.isCoalesced()) { writeBehindConfigurationBuilder = writeBehindConfigurationBuilder.enableCoalescing(); } builder = builder.add(writeBehindConfigurationBuilder); } } if (cacheTemplate.listeners() != null) { for (ConfigurationParser.Listener listener : cacheTemplate.listeners()) { final Class<CacheEventListener<?, ?>> cacheEventListenerClass = (Class<CacheEventListener<?, ?>>) getClassForName(listener.className(), defaultClassLoader); final List<EventType> eventListToFireOn = listener.fireOn(); Set<org.ehcache.event.EventType> eventSetToFireOn = new HashSet<org.ehcache.event.EventType>(); for (EventType events : eventListToFireOn) { switch (events) { case CREATED: eventSetToFireOn.add(org.ehcache.event.EventType.CREATED); break; case EVICTED: eventSetToFireOn.add(org.ehcache.event.EventType.EVICTED); break; case EXPIRED: eventSetToFireOn.add(org.ehcache.event.EventType.EXPIRED); break; case UPDATED: eventSetToFireOn.add(org.ehcache.event.EventType.UPDATED); break; case REMOVED: eventSetToFireOn.add(org.ehcache.event.EventType.REMOVED); break; default: throw new IllegalArgumentException("Invalid Event Type provided"); } } CacheEventListenerConfigurationBuilder listenerBuilder = CacheEventListenerConfigurationBuilder.newEventListenerConfiguration( cacheEventListenerClass, eventSetToFireOn) .firingMode(EventFiring.valueOf(listener.eventFiring().value())) .eventOrdering(EventOrdering.valueOf(listener.eventOrdering().value())); builder = builder.add(listenerBuilder); } } ResourcePoolsBuilder resourcePoolsBuilder = newResourcePoolsBuilder(); for (ResourcePool resourcePool : cacheTemplate.resourcePools()) { resourcePoolsBuilder = resourcePoolsBuilder.with( resourcePool.getType(), resourcePool.getSize(), resourcePool.getUnit(), resourcePool.isPersistent()); } builder = builder.withResourcePools(resourcePoolsBuilder); for (ServiceConfiguration<?> serviceConfiguration : cacheTemplate.serviceConfigs()) { builder = builder.add(serviceConfiguration); } if (cacheTemplate.storeByValueOnHeap() != null) { final OnHeapStoreServiceConfiguration onHeapStoreServiceConfig = new OnHeapStoreServiceConfiguration(); onHeapStoreServiceConfig.storeByValue(cacheTemplate.storeByValueOnHeap()); builder = builder.add(onHeapStoreServiceConfig); } return builder; }
@SuppressWarnings({"rawtypes", "unchecked"}) private void parseConfiguration() throws ClassNotFoundException, IOException, SAXException, InstantiationException, IllegalAccessException { LOGGER.info("Loading Ehcache XML configuration from {}.", xml.getPath()); ConfigurationParser configurationParser = new ConfigurationParser(xml.toExternalForm(), CORE_SCHEMA_URL); final ArrayList<ServiceCreationConfiguration<?>> serviceConfigs = new ArrayList<ServiceCreationConfiguration<?>>(); for (ServiceType serviceType : configurationParser.getServiceElements()) { if (serviceType.getDefaultSerializers() != null) { DefaultSerializationProviderConfiguration configuration = new DefaultSerializationProviderConfiguration(); for (SerializerType.Serializer serializer : serviceType.getDefaultSerializers().getSerializer()) { try { configuration.addSerializerFor( getClassForName(serializer.getType(), classLoader), (Class) getClassForName(serializer.getValue(), classLoader)); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } serviceConfigs.add(configuration); } else if (serviceType.getPersistence() != null) { serviceConfigs.add( new CacheManagerPersistenceConfiguration( new File(serviceType.getPersistence().getDirectory()))); } else { final ServiceCreationConfiguration<?> serviceConfiguration1 = configurationParser.parseExtension((Element) serviceType.getAny()); serviceConfigs.add(serviceConfiguration1); } } for (ServiceCreationConfiguration<?> serviceConfiguration : Collections.unmodifiableList(serviceConfigs)) { serviceConfigurations.add(serviceConfiguration); } for (ConfigurationParser.CacheDefinition cacheDefinition : configurationParser.getCacheElements()) { CacheConfigurationBuilder<Object, Object> builder = CacheConfigurationBuilder.newCacheConfigurationBuilder(); String alias = cacheDefinition.id(); ClassLoader cacheClassLoader = cacheClassLoaders.get(alias); if (cacheClassLoader != null) { builder = builder.withClassLoader(cacheClassLoader); } if (cacheClassLoader == null) { if (classLoader != null) { cacheClassLoader = classLoader; } else { cacheClassLoader = ClassLoading.getDefaultClassLoader(); } } Class keyType = getClassForName(cacheDefinition.keyType(), cacheClassLoader); Class valueType = getClassForName(cacheDefinition.valueType(), cacheClassLoader); if (cacheDefinition.keySerializer() != null) { Class keySerializer = getClassForName(cacheDefinition.keySerializer(), cacheClassLoader); builder = builder.add( new DefaultSerializerConfiguration( keySerializer, DefaultSerializerConfiguration.Type.KEY)); } if (cacheDefinition.valueSerializer() != null) { Class valueSerializer = getClassForName(cacheDefinition.valueSerializer(), cacheClassLoader); builder = builder.add( new DefaultSerializerConfiguration( valueSerializer, DefaultSerializerConfiguration.Type.VALUE)); } EvictionVeto evictionVeto = getInstanceOfName(cacheDefinition.evictionVeto(), cacheClassLoader, EvictionVeto.class); EvictionPrioritizer evictionPrioritizer = getInstanceOfName( cacheDefinition.evictionPrioritizer(), cacheClassLoader, EvictionPrioritizer.class, Eviction.Prioritizer.class); final ConfigurationParser.Expiry parsedExpiry = cacheDefinition.expiry(); if (parsedExpiry != null) { builder = builder.withExpiry(getExpiry(cacheClassLoader, parsedExpiry)); } ResourcePoolsBuilder resourcePoolsBuilder = newResourcePoolsBuilder(); for (ResourcePool resourcePool : cacheDefinition.resourcePools()) { resourcePoolsBuilder = resourcePoolsBuilder.with( resourcePool.getType(), resourcePool.getSize(), resourcePool.getUnit(), resourcePool.isPersistent()); } builder = builder.withResourcePools(resourcePoolsBuilder); for (ServiceConfiguration<?> serviceConfig : cacheDefinition.serviceConfigs()) { builder = builder.add(serviceConfig); } if (cacheDefinition.loaderWriter() != null) { final Class<CacheLoaderWriter<?, ?>> cacheLoaderWriterClass = (Class<CacheLoaderWriter<?, ?>>) getClassForName(cacheDefinition.loaderWriter(), cacheClassLoader); builder = builder.add(new DefaultCacheLoaderWriterConfiguration(cacheLoaderWriterClass)); if (cacheDefinition.writeBehind() != null) { WriteBehind writeBehind = cacheDefinition.writeBehind(); WriteBehindConfigurationBuilder writeBehindConfigurationBuilder = WriteBehindConfigurationBuilder.newWriteBehindConfiguration() .concurrencyLevel(writeBehind.concurrency()) .queueSize(writeBehind.maxQueueSize()) .rateLimit(writeBehind.rateLimitPerSecond()) .retry(writeBehind.retryAttempts(), writeBehind.retryAttemptsDelay()) .delay(writeBehind.minWriteDelay(), writeBehind.maxWriteDelay()); if (writeBehind.isBatched()) { writeBehindConfigurationBuilder = writeBehindConfigurationBuilder.batchSize(writeBehind.batchSize()); } if (writeBehind.isCoalesced()) { writeBehindConfigurationBuilder = writeBehindConfigurationBuilder.enableCoalescing(); } builder = builder.add(writeBehindConfigurationBuilder); } } if (cacheDefinition.listeners() != null) { for (ConfigurationParser.Listener listener : cacheDefinition.listeners()) { final Class<CacheEventListener<?, ?>> cacheEventListenerClass = (Class<CacheEventListener<?, ?>>) getClassForName(listener.className(), cacheClassLoader); final List<EventType> eventListToFireOn = listener.fireOn(); Set<org.ehcache.event.EventType> eventSetToFireOn = new HashSet<org.ehcache.event.EventType>(); for (EventType events : eventListToFireOn) { switch (events) { case CREATED: eventSetToFireOn.add(org.ehcache.event.EventType.CREATED); break; case EVICTED: eventSetToFireOn.add(org.ehcache.event.EventType.EVICTED); break; case EXPIRED: eventSetToFireOn.add(org.ehcache.event.EventType.EXPIRED); break; case UPDATED: eventSetToFireOn.add(org.ehcache.event.EventType.UPDATED); break; case REMOVED: eventSetToFireOn.add(org.ehcache.event.EventType.REMOVED); break; default: throw new IllegalArgumentException("Invalid Event Type provided"); } } CacheEventListenerConfigurationBuilder listenerBuilder = CacheEventListenerConfigurationBuilder.newEventListenerConfiguration( cacheEventListenerClass, eventSetToFireOn) .firingMode(EventFiring.valueOf(listener.eventFiring().value())) .eventOrdering(EventOrdering.valueOf(listener.eventOrdering().value())); builder = builder.add(listenerBuilder); } } if (cacheDefinition.storeByValueOnHeap() != null) { final OnHeapStoreServiceConfiguration onHeapStoreServiceConfig = new OnHeapStoreServiceConfiguration(); onHeapStoreServiceConfig.storeByValue(cacheDefinition.storeByValueOnHeap()); builder = builder.add(onHeapStoreServiceConfig); } final CacheConfiguration<?, ?> config = builder.buildConfig(keyType, valueType, evictionVeto, evictionPrioritizer); cacheConfigurations.put(alias, config); } templates.putAll(configurationParser.getTemplates()); }