|
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()));
|
|
}
|
|
|
|
}
|