/** @author Alex Snaps */ public class StandaloneCacheBuilder<K, V, T extends StandaloneCache<K, V>> { private final Class<K> keyType; private final Class<V> valueType; private Expiry<? super K, ? super V> expiry = Expirations.noExpiration(); private ClassLoader classLoader = ClassLoading.getDefaultClassLoader(); private Comparable<Long> capacityConstraint; private EvictionVeto<? super K, ? super V> evictionVeto; private EvictionPrioritizer<? super K, ? super V> evictionPrioritizer; private CacheLoader<? super K, ? extends V> cacheLoader; private CacheWriter<? super K, ? super V> cacheWriter; private SerializationProvider serializationProvider; private ScheduledExecutorService statisticsExecutor; public StandaloneCacheBuilder(final Class<K> keyType, final Class<V> valueType) { this.keyType = keyType; this.valueType = valueType; } T build(ServiceLocator serviceLocator) { Store.Provider storeProvider = serviceLocator.findService(Store.Provider.class); if (serializationProvider == null) { this.serializationProvider = serviceLocator.findService(SerializationProvider.class); } ExecutorFactoryService executorService = serviceLocator.findService(ExecutorFactoryService.class); if (executorService != null && executorService.getStatisticsExecutor() != null) { statisticsExecutor = executorService.getStatisticsExecutor(); } else { statisticsExecutor = StatisticsThreadPoolUtil.getDefaultStatisticsExecutorService(); } final StoreConfigurationImpl<K, V> storeConfig = new StoreConfigurationImpl<K, V>( keyType, valueType, capacityConstraint, evictionVeto, evictionPrioritizer, classLoader, expiry, serializationProvider); final Store<K, V> store = storeProvider.createStore(storeConfig); CacheConfiguration<K, V> cacheConfig = new BaseCacheConfiguration<K, V>( keyType, valueType, capacityConstraint, evictionVeto, evictionPrioritizer, classLoader, expiry, serializationProvider, new ServiceConfiguration<?>[] {}); final Ehcache<K, V> ehcache = new Ehcache<K, V>(cacheConfig, store, cacheLoader, cacheWriter, statisticsExecutor); return (T) ehcache; } public final T build() { return build(new ServiceLocator()); } public final <N extends T> StandaloneCacheBuilder<K, V, N> with( StandaloneCacheConfiguration<K, V, N> cfg) { return cfg.builder(this); } public final StandaloneCacheBuilder<K, V, T> withCapacity(Comparable<Long> constraint) { capacityConstraint = constraint; return this; } public final StandaloneCacheBuilder<K, V, T> vetoEviction( EvictionVeto<? super K, ? super V> predicate) { this.evictionVeto = predicate; return this; } public final StandaloneCacheBuilder<K, V, T> prioritizeEviction( EvictionPrioritizer<? super K, ? super V> criteria) { this.evictionPrioritizer = criteria; return this; } public final StandaloneCacheBuilder<K, V, T> loadingWith( CacheLoader<? super K, ? extends V> cacheLoader) { this.cacheLoader = cacheLoader; return this; } public final StandaloneCacheBuilder<K, V, T> withClassLoader(ClassLoader classLoader) { if (classLoader == null) { throw new NullPointerException("Null classloader"); } this.classLoader = classLoader; return this; } public final StandaloneCacheBuilder<K, V, T> withExpiry(Expiry<K, V> expiry) { if (expiry == null) { throw new NullPointerException("Null expiry"); } this.expiry = expiry; return this; } public final StandaloneCacheBuilder<K, V, T> writingWith( CacheWriter<? super K, ? super V> cacheWriter) { this.cacheWriter = cacheWriter; return this; } public final StandaloneCacheBuilder<K, V, T> withSerializationProvider( SerializationProvider serializationProvider) { this.serializationProvider = serializationProvider; return this; } public static <K, V, T extends StandaloneCache<K, V>> StandaloneCacheBuilder<K, V, T> newCacheBuilder(Class<K> keyType, Class<V> valueType) { return new StandaloneCacheBuilder<K, V, T>(keyType, valueType); } }
@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()); }
/** * 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; }
/** * Constructs an instance of XmlConfiguration mapping to the XML file located at {@code url} * * <p>Parses the XML file at the {@code url} provided. * * @param url URL pointing to the XML file's location * @throws IOException if anything went wrong accessing the URL * @throws SAXException if anything went wrong parsing or validating the XML * @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 */ public XmlConfiguration(URL url) throws ClassNotFoundException, SAXException, InstantiationException, IllegalAccessException, IOException { this(url, ClassLoading.getDefaultClassLoader()); }