diff --git a/exist-core/src/main/java/org/exist/repo/ExistRepository.java b/exist-core/src/main/java/org/exist/repo/ExistRepository.java index 9e97699c00a..2ff24b8f4a3 100644 --- a/exist-core/src/main/java/org/exist/repo/ExistRepository.java +++ b/exist-core/src/main/java/org/exist/repo/ExistRepository.java @@ -23,12 +23,17 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.exist.dom.persistent.BinaryDocument; +import org.exist.security.PermissionDeniedException; +import org.exist.source.DBSource; import org.exist.storage.BrokerPool; import org.exist.storage.BrokerPoolService; import org.exist.storage.BrokerPoolServiceException; +import org.exist.storage.DBBroker; import org.exist.storage.NativeBroker; import org.exist.util.Configuration; import org.exist.util.FileUtils; +import org.exist.xmldb.XmldbURI; import org.exist.xquery.ErrorCodes; import org.exist.xquery.Expression; import org.exist.xquery.Module; @@ -41,7 +46,9 @@ import org.expath.pkg.repo.PackageException; import org.expath.pkg.repo.Repository; import org.expath.pkg.repo.URISpace; +import org.w3c.dom.Document; +import javax.annotation.Nullable; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import java.io.IOException; @@ -273,6 +280,38 @@ public Path resolveXQueryModule(final String namespace) throws XPathException { return null; } + /** + * Attempt to lookup an XQuery from the filesystem in the database. + * + * @param broker the database broker + * @param xqueryPath the path to the xquery within the EXPath filesystem repo. + * + * @return the database source for the xquery, or null. + */ + public @Nullable org.exist.source.Source resolveStoredXQueryModuleFromDb(final DBBroker broker, final Path xqueryPath) throws PermissionDeniedException { + if (!xqueryPath.startsWith(expathDir)) { + return null; + } + + final String relXQueryPath = expathDir.relativize(xqueryPath).toString(); + + // 1. attempt to locate it within a library + XmldbURI xqueryDbPath = XmldbURI.create("xmldb:exist:///db/system/repo/" + relXQueryPath); + @Nullable Document doc = broker.getXMLResource(xqueryDbPath); + if (doc != null && doc instanceof BinaryDocument) { + return new DBSource(broker, (BinaryDocument) doc, false); + } + + // 2. attempt to locate it within an app + xqueryDbPath = XmldbURI.create("xmldb:exist:///db/apps/" + relXQueryPath); + doc = broker.getXMLResource(xqueryDbPath); + if (doc != null && doc instanceof BinaryDocument) { + return new DBSource(broker, (BinaryDocument) doc, false); + } + + return null; + } + public Source resolveXSLTModule(final String namespace) throws PackageException { for (final Packages pp : myParent.listPackages()) { final Package pkg = pp.latest(); diff --git a/exist-core/src/main/java/org/exist/xquery/XQueryContext.java b/exist-core/src/main/java/org/exist/xquery/XQueryContext.java index 4d95aa38ea3..649ce3fe374 100644 --- a/exist-core/src/main/java/org/exist/xquery/XQueryContext.java +++ b/exist-core/src/main/java/org/exist/xquery/XQueryContext.java @@ -30,6 +30,7 @@ import java.net.URISyntaxException; import java.nio.charset.Charset; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicReference; @@ -588,9 +589,28 @@ public Optional getRepository() { // use the resolved file or return null if (resolved != null) { - // build a module object from the file - final Source src = new FileSource(resolved, false); - return compileOrBorrowModule(prefix, namespace, "", src); + + String location = ""; + + try { + + // see if the src exists in the database and if so, use that instead + Source src = repo.get().resolveStoredXQueryModuleFromDb(getBroker(), resolved); + if (src != null) { + // NOTE(AR) set the location of the module to import relative to this module's load path - so that transient imports of the imported module will resolve correctly! + location = Paths.get(XmldbURI.create(moduleLoadPath).getCollectionPath()).relativize(Paths.get(((DBSource)src).getDocumentPath().getCollectionPath())).toString(); + } else { + // else, fallback to the one from the filesystem + src = new FileSource(resolved, false); + } + + // build a module object from the source + final ExternalModule module = compileOrBorrowModule(prefix, namespace, location, src); + return module; + + } catch (final PermissionDeniedException e) { + throw new XPathException(e.getMessage(), e); + } } } diff --git a/exist-parent/pom.xml b/exist-parent/pom.xml index fd13efce70f..9548945440b 100644 --- a/exist-parent/pom.xml +++ b/exist-parent/pom.xml @@ -394,7 +394,7 @@ org.expath.packaging pkg-java - 2.0.0 + 2.0.1