From 66e6d422e78f5b5d81f186347f893cc09502b407 Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Wed, 27 Jul 2022 16:27:02 -0400 Subject: [PATCH] Use public configuration builder APIs in parser where possible. --- .../ClusteredResourceConfigurationParser.java | 49 ++++++++++--------- .../org/ehcache/core/util/ClassLoading.java | 32 ++++++++++++ .../config/builders/ResourcePoolsBuilder.java | 6 +++ .../impl/config/SizedResourcePoolImpl.java | 7 --- .../xml/ResourceConfigurationParser.java | 49 +++++++------------ .../xml/ResourceConfigurationParser.java | 49 +++++++------------ 6 files changed, 100 insertions(+), 92 deletions(-) diff --git a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java index 44914a166c..17f70f1c02 100644 --- a/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java +++ b/clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/config/xml/ClusteredResourceConfigurationParser.java @@ -16,9 +16,10 @@ package org.ehcache.clustered.client.internal.config.xml; -import org.ehcache.clustered.client.internal.config.ClusteredResourcePoolImpl; -import org.ehcache.clustered.client.internal.config.DedicatedClusteredResourcePoolImpl; -import org.ehcache.clustered.client.internal.config.SharedClusteredResourcePoolImpl; +import org.ehcache.clustered.client.config.ClusteredResourcePool; +import org.ehcache.clustered.client.config.DedicatedClusteredResourcePool; +import org.ehcache.clustered.client.config.SharedClusteredResourcePool; +import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder; import org.ehcache.config.ResourcePool; import org.ehcache.config.units.MemoryUnit; import org.ehcache.xml.CacheResourceConfigurationParser; @@ -57,7 +58,7 @@ public ResourcePool parse(final Element fragment, ClassLoader classLoader) { switch (elementName) { case SHARED_ELEMENT_NAME: final String sharing = parsePropertyOrString(fragment.getAttribute(SHARING_ELEMENT_NAME)); - return new SharedClusteredResourcePoolImpl(sharing); + return ClusteredResourcePoolBuilder.clusteredShared(sharing); case DEDICATED_ELEMENT_NAME: // 'from' attribute is optional on 'clustered-dedicated' element @@ -85,9 +86,9 @@ public ResourcePool parse(final Element fragment, ClassLoader classLoader) { throw new XmlConfigurationException(String.format("XML configuration element <%s> value '%s' is not valid", elementName, sizeValue), e); } - return new DedicatedClusteredResourcePoolImpl(from, size, sizeUnits); + return ClusteredResourcePoolBuilder.clusteredDedicated(from, size, sizeUnits); case CLUSTERED_ELEMENT_NAME: - return new ClusteredResourcePoolImpl(); + return ClusteredResourcePoolBuilder.clustered(); default: return null; } @@ -95,31 +96,33 @@ public ResourcePool parse(final Element fragment, ClassLoader classLoader) { @Override public Element safeUnparse(Document doc, ResourcePool resourcePool) { - Element rootElement = null; - if (ClusteredResourcePoolImpl.class == resourcePool.getClass()) { - rootElement = doc.createElementNS(NAMESPACE, TC_CLUSTERED_NAMESPACE_PREFIX + CLUSTERED_ELEMENT_NAME); - } else if (DedicatedClusteredResourcePoolImpl.class == resourcePool.getClass()) { - DedicatedClusteredResourcePoolImpl dedicatedClusteredResourcePool = (DedicatedClusteredResourcePoolImpl) resourcePool; - rootElement = doc.createElementNS(NAMESPACE, TC_CLUSTERED_NAMESPACE_PREFIX + DEDICATED_ELEMENT_NAME); + if (resourcePool instanceof SharedClusteredResourcePool) { + SharedClusteredResourcePool sharedClusteredResourcePool = (SharedClusteredResourcePool) resourcePool; + Element element = doc.createElementNS(NAMESPACE, TC_CLUSTERED_NAMESPACE_PREFIX + SHARED_ELEMENT_NAME); + element.setAttribute(SHARING_ELEMENT_NAME, sharedClusteredResourcePool.getSharedResourcePool()); + return element; + } else if (resourcePool instanceof DedicatedClusteredResourcePool) { + DedicatedClusteredResourcePool dedicatedClusteredResourcePool = (DedicatedClusteredResourcePool) resourcePool; + Element element = doc.createElementNS(NAMESPACE, TC_CLUSTERED_NAMESPACE_PREFIX + DEDICATED_ELEMENT_NAME); if (dedicatedClusteredResourcePool.getFromResource() != null) { - rootElement.setAttribute(FROM_ELEMENT_NAME, dedicatedClusteredResourcePool.getFromResource()); + element.setAttribute(FROM_ELEMENT_NAME, dedicatedClusteredResourcePool.getFromResource()); } - rootElement.setAttribute(UNIT_ELEMENT_NAME, dedicatedClusteredResourcePool.getUnit().toString()); - rootElement.setTextContent(String.valueOf(dedicatedClusteredResourcePool.getSize())); - } else if (SharedClusteredResourcePoolImpl.class == resourcePool.getClass()) { - SharedClusteredResourcePoolImpl sharedClusteredResourcePool = (SharedClusteredResourcePoolImpl) resourcePool; - rootElement = doc.createElementNS(NAMESPACE, TC_CLUSTERED_NAMESPACE_PREFIX + SHARED_ELEMENT_NAME); - rootElement.setAttribute(SHARING_ELEMENT_NAME, sharedClusteredResourcePool.getSharedResourcePool()); + element.setAttribute(UNIT_ELEMENT_NAME, dedicatedClusteredResourcePool.getUnit().toString()); + element.setTextContent(String.valueOf(dedicatedClusteredResourcePool.getSize())); + return element; + } else if (resourcePool instanceof ClusteredResourcePool) { + return doc.createElementNS(NAMESPACE, TC_CLUSTERED_NAMESPACE_PREFIX + CLUSTERED_ELEMENT_NAME); + } else { + return null; } - return rootElement; } @Override public Set> getResourceTypes() { return Collections.unmodifiableSet(new HashSet<>(Arrays.asList( - ClusteredResourcePoolImpl.class, - DedicatedClusteredResourcePoolImpl.class, - SharedClusteredResourcePoolImpl.class + ClusteredResourcePool.class, + DedicatedClusteredResourcePool.class, + SharedClusteredResourcePool.class ))); } } diff --git a/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java b/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java index a17a34d901..4f7add8f04 100644 --- a/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java +++ b/ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java @@ -28,8 +28,10 @@ import java.util.List; import java.util.ServiceLoader; import java.util.function.Supplier; +import java.util.stream.Stream; import static java.security.AccessController.doPrivileged; +import static java.util.Arrays.asList; import static java.util.Collections.enumeration; import static java.util.Collections.list; import static java.util.stream.Collectors.toList; @@ -66,6 +68,36 @@ public static ClassLoader delegationChain(ClassLoader ... loaders) { return doPrivileged((PrivilegedAction) () -> new ChainedClassLoader(of(loaders).>map(l -> () -> l).collect(toList()))); } + public static double classDistance(Class a, Class b) { + if (a.isAssignableFrom(b)) { + if (a.isInterface()) { + double depth = 0.5; + for (Class t = b; asList(t.getInterfaces()).contains(a); t = b.getSuperclass()) { + depth++; + } + return depth; + } else { + double depth = 0; + for (Class t = b; !a.equals(t); t = b.getSuperclass()) { + depth++; + } + return depth; + } + } else if (b.isAssignableFrom(a)) { + return classDistance(b, a); + } else { + return Double.POSITIVE_INFINITY; + } + }; + + private static Stream> classHierarchy(Class klazz) { + if (Object.class.equals(klazz)) { + return Stream.of(Object.class); + } else { + return Stream.concat(Stream.of(klazz), classHierarchy(klazz.getSuperclass())); + } + } + private static class ChainedClassLoader extends ClassLoader { private final List> loaders; diff --git a/ehcache-impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java b/ehcache-impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java index ed85b7816e..0578a86ed6 100644 --- a/ehcache-impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java +++ b/ehcache-impl/src/main/java/org/ehcache/config/builders/ResourcePoolsBuilder.java @@ -26,6 +26,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.ResourceUnit; import org.ehcache.config.units.MemoryUnit; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; @@ -44,6 +45,8 @@ */ public class ResourcePoolsBuilder implements Builder { + private static final Logger LOGGER = LoggerFactory.getLogger(ResourcePoolsBuilder.class); + private final Map, ResourcePool> resourcePools; private ResourcePoolsBuilder() { @@ -133,6 +136,9 @@ public ResourcePoolsBuilder withReplacing(ResourcePool resourcePool) { * @throws IllegalArgumentException if the set of resource pools already contains a pool for {@code type} */ public ResourcePoolsBuilder with(ResourceType type, long size, ResourceUnit unit, boolean persistent) { + if (type == org.ehcache.config.ResourceType.Core.HEAP && unit instanceof MemoryUnit){ + LOGGER.info("Byte based heap resources are deprecated and will be removed in a future version."); + } return with(new SizedResourcePoolImpl<>(type, size, unit, persistent)); } diff --git a/ehcache-impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java b/ehcache-impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java index 2d35b26900..100ba3c23c 100644 --- a/ehcache-impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java +++ b/ehcache-impl/src/main/java/org/ehcache/impl/config/SizedResourcePoolImpl.java @@ -20,10 +20,7 @@ import org.ehcache.config.ResourceType; import org.ehcache.config.ResourceUnit; import org.ehcache.config.SizedResourcePool; -import org.ehcache.config.units.MemoryUnit; import org.ehcache.core.HumanReadable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Implementation of the {@link SizedResourcePool} interface. @@ -33,7 +30,6 @@ public class SizedResourcePoolImpl

extends AbstractResourcePool> implements SizedResourcePool, HumanReadable { - private static final Logger LOGGER = LoggerFactory.getLogger(SizedResourcePoolImpl.class); private final long size; private final ResourceUnit unit; @@ -56,9 +52,6 @@ public SizedResourcePoolImpl(ResourceType

type, long size, ResourceUnit unit, if (!type.isPersistable() && persistent) { throw new IllegalStateException("Non-persistable resource cannot be configured persistent"); } - if (type == org.ehcache.config.ResourceType.Core.HEAP && unit instanceof MemoryUnit){ - LOGGER.info("Byte based heap resources are deprecated and will be removed in a future version."); - } this.size = size; this.unit = unit; } diff --git a/ehcache-xml/src/jakarta/java/org/ehcache/xml/ResourceConfigurationParser.java b/ehcache-xml/src/jakarta/java/org/ehcache/xml/ResourceConfigurationParser.java index d5fa2f1665..e76d2c70fc 100644 --- a/ehcache-xml/src/jakarta/java/org/ehcache/xml/ResourceConfigurationParser.java +++ b/ehcache-xml/src/jakarta/java/org/ehcache/xml/ResourceConfigurationParser.java @@ -29,7 +29,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.impl.config.SizedResourcePoolImpl; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; @@ -51,11 +50,11 @@ import javax.xml.validation.Schema; import java.math.BigInteger; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.Set; +import static org.ehcache.core.util.ClassLoading.classDistance; import static org.ehcache.xml.XmlConfiguration.CORE_SCHEMA_URL; import static org.ehcache.xml.XmlUtil.newSchema; @@ -87,27 +86,24 @@ public ResourceConfigurationParser(Set extensi public ResourcePools parse(CacheTemplate cacheTemplate, ResourcePoolsBuilder resourcePoolsBuilder, ClassLoader classLoader) { if (cacheTemplate.getHeap() != null) { - resourcePoolsBuilder = resourcePoolsBuilder.with(parseHeapConfiguration(cacheTemplate.getHeap())); + ResourceTypeWithPropSubst heapResource = cacheTemplate.getHeap().getValue(); + resourcePoolsBuilder = resourcePoolsBuilder.heap(heapResource.getValue().longValue(), parseUnit(heapResource)); } else if (!cacheTemplate.getResources().isEmpty()) { for (Element element : cacheTemplate.getResources()) { - ResourcePool resourcePool; - if (!CORE_SCHEMA_NS.equals(element.getNamespaceURI())) { - resourcePool = parseResourceExtension(element, classLoader); - } else { + if (CORE_SCHEMA_NS.equals(element.getNamespaceURI())) { try { Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); unmarshaller.setEventHandler(new DefaultValidationEventHandler()); Object resource = unmarshaller.unmarshal(element); if (resource instanceof Heap) { - resourcePool = parseHeapConfiguration((Heap) resource); + ResourceTypeWithPropSubst heap = ((Heap) resource).getValue(); + resourcePoolsBuilder = resourcePoolsBuilder.heap(heap.getValue().longValue(), parseUnit(heap)); } else if (resource instanceof Offheap) { - MemoryTypeWithPropSubst offheapResource = ((Offheap) resource).getValue(); - resourcePool = new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.OFFHEAP, - offheapResource.getValue().longValue(), parseMemory(offheapResource), false); + MemoryTypeWithPropSubst offheap = ((Offheap) resource).getValue(); + resourcePoolsBuilder = resourcePoolsBuilder.offheap(offheap.getValue().longValue(), parseMemory(offheap)); } else if (resource instanceof Disk) { - PersistableMemoryTypeWithPropSubst diskResource = ((Disk) resource).getValue(); - resourcePool = new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.DISK, - diskResource.getValue().longValue(), parseMemory(diskResource), diskResource.isPersistent()); + PersistableMemoryTypeWithPropSubst disk = ((Disk) resource).getValue(); + resourcePoolsBuilder = resourcePoolsBuilder.disk(disk.getValue().longValue(), parseMemory(disk), disk.isPersistent()); } else { // Someone updated the core resources without updating *this* code ... throw new AssertionError("Unrecognized resource: " + element + " / " + resource.getClass().getName()); @@ -115,9 +111,9 @@ public ResourcePools parse(CacheTemplate cacheTemplate, ResourcePoolsBuilder res } catch (JAXBException e) { throw new IllegalArgumentException("Can't find parser for resource: " + element, e); } + } else { + resourcePoolsBuilder = resourcePoolsBuilder.with(parseResourceExtension(element, classLoader)); } - - resourcePoolsBuilder = resourcePoolsBuilder.with(resourcePool); } } else { throw new XmlConfigurationException("No resources defined for the cache: " + cacheTemplate.id()); @@ -126,12 +122,6 @@ public ResourcePools parse(CacheTemplate cacheTemplate, ResourcePoolsBuilder res return resourcePoolsBuilder.build(); } - private ResourcePool parseHeapConfiguration(Heap heap) { - ResourceTypeWithPropSubst heapResource = heap.getValue(); - return new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.HEAP, - heapResource.getValue().longValue(), parseUnit(heapResource), false); - } - private static ResourceUnit parseUnit(ResourceTypeWithPropSubst resourceType) { if (resourceType.getUnit().equals(org.ehcache.xml.model.ResourceUnit.ENTRIES)) { return EntryUnit.ENTRIES; @@ -190,14 +180,11 @@ public CacheType unparse(Document target, ResourcePools resourcePools, CacheType throw new XmlConfigurationException(e); } } else { - Map, CacheResourceConfigurationParser> parsers = new HashMap<>(); - extensionParsers.forEach(parser -> parser.getResourceTypes().forEach(rt -> parsers.put(rt, parser))); - CacheResourceConfigurationParser parser = parsers.get(resourcePool.getClass()); - if (parser != null) { - resources.add(parser.unparse(target, resourcePool)); - } else { - throw new AssertionError("Parser not found for resource type: " + resourceType); - } + CacheResourceConfigurationParser parser = extensionParsers.stream().min(Comparator.comparing(p -> p.getResourceTypes().stream() + .mapToDouble(rt -> classDistance(rt, resourcePool.getClass())).min().orElse(Double.POSITIVE_INFINITY))) + .orElseThrow(() -> new AssertionError("Parser not found for resource type: " + resourceType)); + + resources.add(parser.unparse(target, resourcePool)); } }); return cacheType.withResources(OBJECT_FACTORY.createResourcesType().withResource(resources)); diff --git a/ehcache-xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java b/ehcache-xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java index dc5648a799..e29d4bfdaf 100644 --- a/ehcache-xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java +++ b/ehcache-xml/src/main/java/org/ehcache/xml/ResourceConfigurationParser.java @@ -23,7 +23,6 @@ import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.EntryUnit; import org.ehcache.config.units.MemoryUnit; -import org.ehcache.impl.config.SizedResourcePoolImpl; import org.ehcache.xml.exceptions.XmlConfigurationException; import org.ehcache.xml.model.CacheTemplate; import org.ehcache.xml.model.CacheType; @@ -43,9 +42,8 @@ import java.math.BigInteger; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.Set; import javax.xml.bind.JAXBContext; @@ -56,6 +54,7 @@ import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; +import static org.ehcache.core.util.ClassLoading.classDistance; import static org.ehcache.xml.XmlConfiguration.CORE_SCHEMA_URL; import static org.ehcache.xml.XmlUtil.newSchema; @@ -87,27 +86,24 @@ public ResourceConfigurationParser(Set extensi public ResourcePools parse(CacheTemplate cacheTemplate, ResourcePoolsBuilder resourcePoolsBuilder, ClassLoader classLoader) { if (cacheTemplate.getHeap() != null) { - resourcePoolsBuilder = resourcePoolsBuilder.with(parseHeapConfiguration(cacheTemplate.getHeap())); + ResourceTypeWithPropSubst heapResource = cacheTemplate.getHeap().getValue(); + resourcePoolsBuilder = resourcePoolsBuilder.heap(heapResource.getValue().longValue(), parseUnit(heapResource)); } else if (!cacheTemplate.getResources().isEmpty()) { for (Element element : cacheTemplate.getResources()) { - ResourcePool resourcePool; - if (!CORE_SCHEMA_NS.equals(element.getNamespaceURI())) { - resourcePool = parseResourceExtension(element, classLoader); - } else { + if (CORE_SCHEMA_NS.equals(element.getNamespaceURI())) { try { Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); unmarshaller.setEventHandler(new DefaultValidationEventHandler()); Object resource = unmarshaller.unmarshal(element); if (resource instanceof Heap) { - resourcePool = parseHeapConfiguration((Heap) resource); + ResourceTypeWithPropSubst heap = ((Heap) resource).getValue(); + resourcePoolsBuilder = resourcePoolsBuilder.heap(heap.getValue().longValue(), parseUnit(heap)); } else if (resource instanceof Offheap) { - MemoryTypeWithPropSubst offheapResource = ((Offheap) resource).getValue(); - resourcePool = new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.OFFHEAP, - offheapResource.getValue().longValue(), parseMemory(offheapResource), false); + MemoryTypeWithPropSubst offheap = ((Offheap) resource).getValue(); + resourcePoolsBuilder = resourcePoolsBuilder.offheap(offheap.getValue().longValue(), parseMemory(offheap)); } else if (resource instanceof Disk) { - PersistableMemoryTypeWithPropSubst diskResource = ((Disk) resource).getValue(); - resourcePool = new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.DISK, - diskResource.getValue().longValue(), parseMemory(diskResource), diskResource.isPersistent()); + PersistableMemoryTypeWithPropSubst disk = ((Disk) resource).getValue(); + resourcePoolsBuilder = resourcePoolsBuilder.disk(disk.getValue().longValue(), parseMemory(disk), disk.isPersistent()); } else { // Someone updated the core resources without updating *this* code ... throw new AssertionError("Unrecognized resource: " + element + " / " + resource.getClass().getName()); @@ -115,9 +111,9 @@ public ResourcePools parse(CacheTemplate cacheTemplate, ResourcePoolsBuilder res } catch (JAXBException e) { throw new IllegalArgumentException("Can't find parser for resource: " + element, e); } + } else { + resourcePoolsBuilder = resourcePoolsBuilder.with(parseResourceExtension(element, classLoader)); } - - resourcePoolsBuilder = resourcePoolsBuilder.with(resourcePool); } } else { throw new XmlConfigurationException("No resources defined for the cache: " + cacheTemplate.id()); @@ -126,12 +122,6 @@ public ResourcePools parse(CacheTemplate cacheTemplate, ResourcePoolsBuilder res return resourcePoolsBuilder.build(); } - private ResourcePool parseHeapConfiguration(Heap heap) { - ResourceTypeWithPropSubst heapResource = heap.getValue(); - return new SizedResourcePoolImpl<>(org.ehcache.config.ResourceType.Core.HEAP, - heapResource.getValue().longValue(), parseUnit(heapResource), false); - } - private static ResourceUnit parseUnit(ResourceTypeWithPropSubst resourceType) { if (resourceType.getUnit().equals(org.ehcache.xml.model.ResourceUnit.ENTRIES)) { return EntryUnit.ENTRIES; @@ -190,14 +180,11 @@ public CacheType unparse(Document target, ResourcePools resourcePools, CacheType throw new XmlConfigurationException(e); } } else { - Map, CacheResourceConfigurationParser> parsers = new HashMap<>(); - extensionParsers.forEach(parser -> parser.getResourceTypes().forEach(rt -> parsers.put(rt, parser))); - CacheResourceConfigurationParser parser = parsers.get(resourcePool.getClass()); - if (parser != null) { - resources.add(parser.unparse(target, resourcePool)); - } else { - throw new AssertionError("Parser not found for resource type: " + resourceType); - } + CacheResourceConfigurationParser parser = extensionParsers.stream().min(Comparator.comparing(p -> p.getResourceTypes().stream() + .mapToDouble(rt -> classDistance(rt, resourcePool.getClass())).min().orElse(Double.POSITIVE_INFINITY))) + .orElseThrow(() -> new AssertionError("Parser not found for resource type: " + resourceType)); + + resources.add(parser.unparse(target, resourcePool)); } }); return cacheType.withResources(OBJECT_FACTORY.createResourcesType().withResource(resources));