Skip to content

Commit

Permalink
Use public configuration builder APIs in parser where possible.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdennis committed Aug 16, 2022
1 parent c09439b commit 66e6d42
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -85,41 +86,43 @@ 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;
}
}

@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<Class<? extends ResourcePool>> getResourceTypes() {
return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
ClusteredResourcePoolImpl.class,
DedicatedClusteredResourcePoolImpl.class,
SharedClusteredResourcePoolImpl.class
ClusteredResourcePool.class,
DedicatedClusteredResourcePool.class,
SharedClusteredResourcePool.class
)));
}
}
32 changes: 32 additions & 0 deletions ehcache-core/src/main/java/org/ehcache/core/util/ClassLoading.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -66,6 +68,36 @@ public static ClassLoader delegationChain(ClassLoader ... loaders) {
return doPrivileged((PrivilegedAction<ClassLoader>) () -> new ChainedClassLoader(of(loaders).<Supplier<ClassLoader>>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<Class<?>> 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<Supplier<ClassLoader>> loaders;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -44,6 +45,8 @@
*/
public class ResourcePoolsBuilder implements Builder<ResourcePools> {

private static final Logger LOGGER = LoggerFactory.getLogger(ResourcePoolsBuilder.class);

private final Map<ResourceType<?>, ResourcePool> resourcePools;

private ResourcePoolsBuilder() {
Expand Down Expand Up @@ -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<SizedResourcePool> 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));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -33,7 +30,6 @@
public class SizedResourcePoolImpl<P extends SizedResourcePool> extends AbstractResourcePool<P, ResourceType<P>>
implements SizedResourcePool, HumanReadable {

private static final Logger LOGGER = LoggerFactory.getLogger(SizedResourcePoolImpl.class);
private final long size;
private final ResourceUnit unit;

Expand All @@ -56,9 +52,6 @@ public SizedResourcePoolImpl(ResourceType<P> 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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -87,37 +86,34 @@ public ResourceConfigurationParser(Set<CacheResourceConfigurationParser> 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());
}
} 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());
Expand All @@ -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;
Expand Down Expand Up @@ -190,14 +180,11 @@ public CacheType unparse(Document target, ResourcePools resourcePools, CacheType
throw new XmlConfigurationException(e);
}
} else {
Map<Class<? extends ResourcePool>, 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));
Expand Down
Loading

0 comments on commit 66e6d42

Please sign in to comment.