Project

Profile

Help

Feature #6395 ยป TestSaxonFeature.java

Joshua Maurice, 2024-04-15 21:15

 
package com.jmaurice;

import java.io.File;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.FileUtils;

import com.informatica.hephaestus.saxon.HephaestusStaticContext;
import com.informatica.hephaestus.saxon.SaxonConfigurationEEv11;
import com.informatica.hephaestus.saxon.XQueryCustomFunctions;
import com.saxonica.config.EnterpriseConfiguration;

import net.sf.saxon.Configuration;
import net.sf.saxon.event.Builder;
import net.sf.saxon.lib.FeatureKeys;
import net.sf.saxon.lib.ModuleURIResolver;
import net.sf.saxon.lib.StaticQueryContextFactory;
import net.sf.saxon.query.StaticQueryContext;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.XQueryCompiler;
import net.sf.saxon.s9api.XQueryExecutable;

public class TestSaxonFeature {
private static int test = 4;

public static void main(String[] args) throws Exception {
final String root = "C:/cygwin64/home/jmaurice/ws1/src/saxon/src/main/resources/com/informatica/hephaestus/xquery";
final List<File> libraryFiles = new ArrayList<>(Arrays.asList(new File(root).listFiles())
.stream()
.filter(f -> f.getName().endsWith(".xq"))
.map(f -> f.getAbsoluteFile())
.sorted()
.toList());
System.out.println("libraryFiles: " + libraryFiles);
//key is moduleUri, value is text file content
final Map<String, String> libraryContents = new LinkedHashMap<>();
for (final File file : libraryFiles) {
final String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
final Pattern p = Pattern.compile("(?m)^ *module +namespace +[a-zA-Z0-9]+ *= *['\"]([a-zA-Z0-9:./]*)['\"] *; *$");
final Matcher m = p.matcher(content);
if ( ! m.find())
throw new RuntimeException();
final String moduleUri = m.group(1);
System.out.println("Library: ModuleUri [" + moduleUri + "]; file [" + file + "]");
libraryContents.put(moduleUri, content);
}
final ModuleURIResolver resolveEverything = (moduleUri, baseUri, hints) -> {
// System.out.println("ResolveEverything resolver called for moduleUri [" + moduleUri
// + "], baseUri [" + baseUri
// + "], hints [" + Arrays.asList(hints)
// + "]");
final String content = libraryContents.get(moduleUri);
if (content != null) {
// System.out.println("moduleUri resolved");
final StreamSource source = new StreamSource(new StringReader(content), moduleUri);
return new StreamSource[]{ source };
}
// System.out.println("moduleUri not found");
return new StreamSource[]{};
};

final ModuleURIResolver resolveNothing = (moduleUri, baseUri, hints) -> {
if (moduleUri.equals("http://www.w3.org/2005/xpath-functions/math"))
return new StreamSource[]{}; //nothing to resolve
throw new RuntimeException("ResolveNothing resolver called with moduleUri ["
+ moduleUri + "], baseUri [" + baseUri + "], hints [" + Arrays.asList(hints) + "]");
};
final EnterpriseConfiguration configuration = new EnterpriseConfiguration();
configuration.importLicenseDetails(SaxonConfigurationEEv11.getLicenseDetails());
configuration.setTreeModel(Builder.TINY_TREE);
configuration.setConfigurationProperty(FeatureKeys.XQUERY_VERSION, "3.1");
configuration.setBooleanProperty(FeatureKeys.XQUERY_MULTIPLE_MODULE_IMPORTS, false);
configuration.setBooleanProperty(FeatureKeys.GENERATE_BYTE_CODE, false);
//Use a custom StaticContext subclass as part of the workaround for https://saxonica.plan.io/issues/2429
configuration.setStaticQueryContextFactory(new StaticQueryContextFactory() {
@Override public StaticQueryContext newStaticQueryContext(final Configuration config, boolean copyFromDefault) {
return new HephaestusStaticContext((EnterpriseConfiguration)config, copyFromDefault);
}
});
final Processor processor = new Processor(configuration);
//Call processor.registerExtensionFunction((ExtensionFunctionDefinition)func)
//for a bunch of functions with Java code definitions which are referenced by my xquery xq library files.
XQueryCustomFunctions.configure(processor);
final XQueryCompiler compiler = processor.newXQueryCompiler();
compiler.setModuleURIResolver(test == 2 ? resolveEverything : resolveNothing);
if (test == 3 || test == 4) {
//precompile the xquery libraries
final XQueryCompiler precompiler = processor.newXQueryCompiler();
final StaticQueryContext precompilerStaticContext = precompiler.getUnderlyingStaticContext();
precompilerStaticContext.setModuleURIResolver(resolveEverything);
for (final Map.Entry<String, String> e : libraryContents.entrySet()) {
final String moduleUri = e.getKey();
final String content = e.getValue();
System.out.println("calling CompileLibrary for moduleUri: " + moduleUri);
precompilerStaticContext.setBaseURI(moduleUri);
//Use the StaticQueryContext as part of the workaround for https://saxonica.plan.io/issues/2429
precompilerStaticContext.compileLibrary(new StringReader(content));
}
//Take the precompiled libraries and put them in the new XQueryCompiler object
//as part of the workaround for https://saxonica.plan.io/issues/2429
((HephaestusStaticContext)compiler.getUnderlyingStaticContext())
.setCompiledLibraries(precompilerStaticContext.getCompiledLibraries());
}
final String importModuleStatements =
(test == 2 || test == 4) ? """
import module namespace dsig="urn:activevos:spi:functions:signature";
import module namespace hash="urn:activevos:spi:functions:hash";
import module namespace list="urn:activevos:spi:list:functions";
import module namespace math="http://www.w3.org/2005/xpath-functions/math";
import module namespace request="urn:activevos:spi:functions:request:context";
import module namespace sff="urn:activevos:spi:functions";
import module namespace util="urn:activevos:spi:functions:utilities";
"""
: "";
final Instant startTime = Instant.now();
try {
final List<XQueryExecutable> cache = new ArrayList<>();
final Random rand = new Random();
for (int i = 0; ; ++i) {
System.out.println(i + "; " + Duration.between(startTime, Instant.now()));
final String query = ""
+ "xquery version \"3.0\" encoding \"utf-8\";\n"
+ importModuleStatements
+ "'" + rand.nextInt() + "'";
final XQueryExecutable queryExecutionPlan = compiler.compile(new StringReader(query));
cache.add(queryExecutionPlan);
}
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
System.out.println(Duration.between(startTime, Instant.now()));
}

}
    (1-1/1)