Skip to content

Commit 8b3afcd

Browse files
committed
[feature] introduce caffeine library as cache for Grammars (XSDs, DTDs)
1 parent 280257a commit 8b3afcd

File tree

11 files changed

+370
-202
lines changed

11 files changed

+370
-202
lines changed

exist-core/src/main/java/org/exist/util/Configuration.java

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,22 +1196,64 @@ private void configureValidation(final Optional<Path> dbHome, final Element vali
11961196
// Determine validation mode
11971197
configureProperty(validation, XMLReaderObjectFactory.VALIDATION_MODE_ATTRIBUTE, PROPERTY_VALIDATION_MODE);
11981198

1199-
// cache
1200-
setProperty(XMLReaderObjectFactory.GRAMMAR_POOL, new GrammarPool());
1201-
12021199
// Configure the Entity Resolver
1203-
final NodeList entityResolver = validation.getElementsByTagName(XMLReaderObjectFactory.CONFIGURATION_ENTITY_RESOLVER_ELEMENT_NAME);
1204-
if (entityResolver.getLength() == 0) {
1205-
return;
1200+
final NodeList entityResolverElements = validation.getElementsByTagName(XMLReaderObjectFactory.CONFIGURATION_ENTITY_RESOLVER_ELEMENT_NAME);
1201+
if (entityResolverElements.getLength() != 0) {
1202+
final Element elemEntityResolver = (Element) entityResolverElements.item(0);
1203+
configureEntityResolver(dbHome, elemEntityResolver);
12061204
}
1205+
1206+
// Configure the grammar pool
1207+
final NodeList grammarPoolElements = validation.getElementsByTagName(GrammarPool.GRAMMAR_POOL_ELEMENT);
1208+
configureGrammarCache(grammarPoolElements);
1209+
1210+
}
1211+
1212+
private void configureGrammarCache(final NodeList grammarCacheElements) {
1213+
if (grammarCacheElements.getLength() == 0) {
1214+
setProperty(GrammarPool.GRAMMAR_POOL_ELEMENT, new GrammarPool());
1215+
1216+
} else {
1217+
final Element grammarPoolElem = (Element) grammarCacheElements.item(0);
1218+
configureProperty(grammarPoolElem, GrammarPool.ATTRIBUTE_MAXIMUM_SIZE,
1219+
GrammarPool.PROPERTY_MAXIMUM_SIZE, Configuration::asInteger, null);
1220+
configureProperty(grammarPoolElem, GrammarPool.ATTRIBUTE_EXPIRE_AFTER_ACCESS,
1221+
GrammarPool.PROPERTY_EXPIRE_AFTER_ACCESS, Configuration::asInteger, null);
1222+
setProperty(GrammarPool.GRAMMAR_POOL_ELEMENT,
1223+
new GrammarPool(getInteger(GrammarPool.PROPERTY_MAXIMUM_SIZE), getInteger(GrammarPool.PROPERTY_EXPIRE_AFTER_ACCESS)));
1224+
}
1225+
}
1226+
1227+
private void configureEntityResolver(final Optional<Path> dbHome, final Element entityResolverElement) {
12071228
LOG.info("Creating xmlresolver.org OASIS Catalog resolver");
12081229

1209-
final Element elemEntityResolver = (Element) entityResolver.item(0);
1210-
final NodeList nlCatalogs = elemEntityResolver.getElementsByTagName(XMLReaderObjectFactory.CONFIGURATION_CATALOG_ELEMENT_NAME);
1230+
final NodeList catalogElements = entityResolverElement
1231+
.getElementsByTagName(XMLReaderObjectFactory.CONFIGURATION_CATALOG_ELEMENT_NAME);
1232+
final Path webappHome = getWebappHome(dbHome, catalogElements);
1233+
1234+
// Store all configured URIs
1235+
final List<String> catalogUris = getCatalogUris(dbHome, catalogElements, webappHome);
1236+
setProperty(XMLReaderObjectFactory.CATALOG_URIS, catalogUris);
1237+
1238+
// Create and Store the resolver
1239+
try {
1240+
final List<Tuple2<String, Optional<InputSource>>> catalogs = catalogUris.stream()
1241+
.map(catalogUri -> Tuple(catalogUri, Optional.<InputSource>empty()))
1242+
.toList();
1243+
final Resolver resolver = ResolverFactory.newResolver(catalogs);
1244+
setProperty(XMLReaderObjectFactory.CATALOG_RESOLVER, resolver);
1245+
} catch (final URISyntaxException e) {
1246+
LOG.error("Unable to parse catalog uri: {}", e.getMessage(), e);
1247+
}
1248+
}
1249+
1250+
/*
1251+
Determine webapps directory. SingleInstanceConfiguration cannot
1252+
be used at this phase. Trick is to check whether dbHOME is
1253+
pointing to a WEB-INF directory, meaning inside the war file.
1254+
*/
1255+
private static Path getWebappHome(final Optional<Path> dbHome, final NodeList catalogElements) {
12111256

1212-
// Determine webapps directory. SingleInstanceConfiguration cannot
1213-
// be used at this phase. Trick is to check whether dbHOME is
1214-
// pointing to a WEB-INF directory, meaning inside the war file.
12151257
final Path webappHome = dbHome.map(h -> {
12161258
if (FileUtils.fileName(h).endsWith("WEB-INF")) {
12171259
return h.getParent().toAbsolutePath();
@@ -1220,15 +1262,18 @@ private void configureValidation(final Optional<Path> dbHome, final Element vali
12201262
}).orElse(Paths.get("webapp").toAbsolutePath());
12211263

12221264
if (LOG.isDebugEnabled()) {
1223-
LOG.debug("Found {} catalog uri entries.", nlCatalogs.getLength());
1265+
LOG.debug("Found {} catalog uri entries.", catalogElements.getLength());
12241266
LOG.debug("Using dbHome={}", dbHome);
12251267
LOG.debug("using webappHome={}", webappHome);
12261268
}
1269+
return webappHome;
1270+
}
12271271

1272+
private static List<String> getCatalogUris(final Optional<Path> dbHome, final NodeList catalogElements, final Path webappHome) {
12281273
// Get the Catalog URIs
12291274
final List<String> catalogUris = new ArrayList<>();
1230-
for (int i = 0; i < nlCatalogs.getLength(); i++) {
1231-
final String uriAttributeValue = ((Element) nlCatalogs.item(i)).getAttribute("uri");
1275+
for (int i = 0; i < catalogElements.getLength(); i++) {
1276+
final String uriAttributeValue = ((Element) catalogElements.item(i)).getAttribute("uri");
12321277

12331278
if (!uriAttributeValue.isEmpty()) {
12341279
final String uri;
@@ -1246,20 +1291,7 @@ private void configureValidation(final Optional<Path> dbHome, final Element vali
12461291
catalogUris.add(uri);
12471292
}
12481293
}
1249-
1250-
// Store all configured URIs
1251-
setProperty(XMLReaderObjectFactory.CATALOG_URIS, catalogUris);
1252-
1253-
// Create and Store the resolver
1254-
try {
1255-
final List<Tuple2<String, Optional<InputSource>>> catalogs = catalogUris.stream()
1256-
.map(catalogUri -> Tuple(catalogUri, Optional.<InputSource>empty()))
1257-
.toList();
1258-
final Resolver resolver = ResolverFactory.newResolver(catalogs);
1259-
setProperty(XMLReaderObjectFactory.CATALOG_RESOLVER, resolver);
1260-
} catch (final URISyntaxException e) {
1261-
LOG.error("Unable to parse catalog uri: {}", e.getMessage(), e);
1262-
}
1294+
return catalogUris;
12631295
}
12641296

12651297
private void configureRpcServer(final Element validation) throws DatabaseConfigurationException {

exist-core/src/main/java/org/exist/util/XMLReaderObjectFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ public class XMLReaderObjectFactory extends BasePooledObjectFactory<XMLReader> i
6060
public static final String PROPERTY_VALIDATION_MODE = "validation.mode";
6161
public static final String CATALOG_RESOLVER = "validation.resolver";
6262
public static final String CATALOG_URIS = "validation.catalog_uris";
63-
public static final String GRAMMAR_POOL = "validation.grammar_pool";
6463

6564
// Xerces feature and property names
6665
public static final String APACHE_FEATURES_VALIDATION_SCHEMA
@@ -83,7 +82,7 @@ public class XMLReaderObjectFactory extends BasePooledObjectFactory<XMLReader> i
8382

8483
@Override
8584
public void configure(final Configuration configuration) {
86-
this.grammarPool = (GrammarPool) configuration.getProperty(XMLReaderObjectFactory.GRAMMAR_POOL);
85+
this.grammarPool = (GrammarPool) configuration.getProperty(GrammarPool.GRAMMAR_POOL_ELEMENT);
8786
this.resolver = (Resolver) configuration.getProperty(CATALOG_RESOLVER);
8887
final String option = (String) configuration.getProperty(PROPERTY_VALIDATION_MODE);
8988
this.validation = VALIDATION_SETTING.fromOption(option);

0 commit comments

Comments
 (0)