diff --git a/elemental-media-type/elemental-media-type-api/pom.xml b/elemental-media-type/elemental-media-type-api/pom.xml
new file mode 100644
index 0000000000..1e29fb8211
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-api/pom.xml
@@ -0,0 +1,84 @@
+
+
+
+ 4.0.0
+
+
+ xyz.elemental
+ elemental-media-type
+ 7.5.0-SNAPSHOT
+ ..
+
+
+ elemental-media-type-api
+
+ Elemental Internet Media Type Resolver API
+ Internet Media Type Resolver API for Elemental
+
+
+ scm:git:https://github.com/evolvedbinary/elemental.git
+ scm:git:https://github.com/evolvedbinary/elemental.git
+ scm:git:https://github.com/evolvedbinary/elemental.git
+
+
+
+
+ com.google.code.findbugs
+ jsr305
+
+
+
+
+
+
+ com.mycila
+ license-maven-plugin
+
+
+
+ ${project.parent.relativePath}/../elemental-parent/FDB-backport-to-EDB-LGPL-21-ONLY-license.template.txt
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaType.java b/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaType.java
new file mode 100644
index 0000000000..ee5c1f792d
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaType.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype;
+
+import javax.annotation.Nullable;
+
+/**
+ * Information about a Media Type (aka MIME Type)
+ * and how resources of that type should be stored into
+ * the database.
+ *
+ * @author Adam Retter
+ */
+public interface MediaType {
+
+ /**
+ * Get the identifier of the Media Type.
+ *
+ * For example {@code application/xml}.
+ *
+ * @return the identifier of the Media Type
+ */
+ String getIdentifier();
+
+ /**
+ * Get the file extensions that are known
+ * to be associated with the Media Type.
+ *
+ * @return the known file extensions associated with the Media Type, or null if there are none
+ */
+ @Nullable String[] getKnownFileExtensions();
+
+ /**
+ * Get the database storage type that should
+ * be used for resources of this Media Type.
+ *
+ * @return the database storage type of the Media Type
+ */
+ StorageType getStorageType();
+
+ //
+ String APPLICATION_ATOM = "application/atom+xml";
+ String APPLICATION_BZIP2 = "application/x-bzip2";
+ String APPLICATION_DITA = "application/dita+xml";
+ String APPLICATION_ELEMENTAL_DOCUMENT = "application/vnd.elemental.document";
+ String APPLICATION_ELEMENTAL_DOCUMENT_BINARY = "application/vnd.elemental.document+binary";
+ String APPLICATION_ELEMENTAL_DOCUMENT_XML = "application/vnd.elemental.document+xml";
+ String APPLICATION_ELEMENTAL_COLLECTION = "application/vnd.elemental.collection";
+ String APPLICATION_EXPATH_PACKAGE_ZIP = "application/prs.expath.package+zip";
+ String APPLICATION_GML = "application/gml+xml";
+ String APPLICATION_GZIP = "application/gzip";
+ String APPLICATION_INVISIBLE_XML_GRAMMAR = "application/prs.invisible-xml.grammar";
+ String APPLICATION_INVISIBLE_XML_GRAMMAR_XML = "application/prs.invisible-xml.grammar+xml";
+ String APPLICATION_JAVA_ARCHIVE = "application/java-archive";
+ String APPLICATION_JSON = "application/json";
+ String APPLICATION_MADS = "application/mads+xml";
+ String APPLICATION_MARC = "application/marcxml+xml";
+ String APPLICATION_METS = "application/mets+xml";
+ String APPLICATION_MODS = "application/mods+xml";
+ String APPLICATION_NCX = "application/x-dtbncx+xml";
+ String APPLICATION_OCTET_STREAM = "application/octet-stream";
+ String APPLICATION_OEBPS_PACKAGE = "application/oebps-package+xml";
+ String APPLICATION_OPENDOCUMENT_PRESENTATION = "application/vnd.oasis.opendocument.presentation";
+ String APPLICATION_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text";
+ String APPLICATION_OPENDOCUMENT_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet";
+ String APPLICATION_OPENXML_PRESENTATION = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
+ String APPLICATION_OPENXML_SPREADSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
+ String APPLICATION_OPENXML_WORDPROCESSING = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
+ String APPLICATION_PACK200 = "application/x-java-pack200";
+ String APPLICATION_PDF = "application/pdf";
+ String APPLICATION_RDF_XML = "application/rdf+xml";
+ String APPLICATION_RELAXNG_COMPACT = "application/relax-ng-compact-syntax";
+ String APPLICATION_RSS = "application/rss+xml";
+ String APPLICATION_SCHEMATRON = "application/schematron+xml";
+ String APPLICATION_SRU = "application/sru+xml";
+ String APPLICATION_TAR = "application/x-tar";
+ String APPLICATION_TEI = "application/tei+xml";
+ String APPLICATION_WSDL = "application/wsdl+xml";
+ String APPLICATION_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
+ String APPLICATION_XMI = "application/vnd.xmi+xml";
+ String APPLICATION_XML = "application/xml";
+ String APPLICATION_XML_DTD = "application/xml-dtd";
+ String APPLICATION_XHTML = "application/xhtml+xml";
+ String APPLICATION_XPROC = "application/xproc+xml";
+ String APPLICATION_XSLT = "application/xslt+xml";
+ String APPLICATION_XQUERY = "application/xquery";
+ String APPLICATION_XQUERY_XML = "application/xquery+xml";
+ String APPLICATION_XZ = "application/x-xz";
+ String APPLICATION_ZIP = "application/zip";
+ String APPLICATION_ZSTD = "application/zstd";
+
+ String IMAGE_GIF = "image/gif";
+ String IMAGE_JPEG = "image/jpeg";
+ String IMAGE_PNG = "image/png";
+ String IMAGE_SVG = "image/svg+xml";
+ String IMAGE_SVG_GZIP = "image/svg+xml";
+ // See: https://github.com/w3c/svgwg/issues/701
+// String IMAGE_SVG_GZIP = "image/x.svg+gzip";
+
+ String MULTIPART_ALTERNATIVE = "multipart/alternative";
+ String MULTIPART_MIXED = "multipart/mixed";
+
+ String TEXT_CSS = "text/css";
+ String TEXT_CSV = "text/csv";
+ String TEXT_CSV_SCHEMA = "text/csv-schema";
+ String TEXT_HTML = "text/html";
+ String TEXT_JAVASCRIPT = "text/javascript";
+ String TEXT_MARKDOWN = "text/markdown";
+ String TEXT_N3 = "text/n3";
+ String TEXT_PLAIN = "text/plain";
+ String TEXT_TURTLE = "text/turtle";
+ String TEXT_URI_LIST = "text/uri-list";
+
+ /**
+ * Expect for use within the type attribute of an XML Processing Instruction
+ * this is probably not what you need, and you should likely use {@link #APPLICATION_XML} instead.
+ */
+ @Deprecated
+ String TEXT_XSL = "text/xsl";
+ //
+
+ //
+ String APPLICATION_EXISTDB_COLLECTION_CONFIG_XML = "application/prs.existdb.collection-config+xml";
+
+ /**
+ * Use {@link #APPLICATION_ELEMENTAL_DOCUMENT} instead.
+ */
+ @Deprecated
+ String APPLICATION_EXISTDB_DOCUMENT = "application/vnd.existdb.document";
+
+ /**
+ * Use {@link #APPLICATION_ELEMENTAL_DOCUMENT_BINARY} instead.
+ */
+ @Deprecated
+ String APPLICATION_EXISTDB_DOCUMENT_BINARY = "application/vnd.existdb.document+binary";
+
+ /**
+ * Use {@link #APPLICATION_ELEMENTAL_DOCUMENT_XML} instead.
+ */
+ @Deprecated
+ String APPLICATION_EXISTDB_DOCUMENT_XML = "application/vnd.existdb.document+xml";
+
+ /**
+ * Use {@link #APPLICATION_ELEMENTAL_COLLECTION} instead.
+ */
+ @Deprecated
+ String APPLICATION_EXISTDB_COLLECTION = "application/vnd.existdb.collection";
+ //
+}
diff --git a/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaTypeResolver.java b/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaTypeResolver.java
new file mode 100644
index 0000000000..575a43806d
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaTypeResolver.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype;
+
+import javax.annotation.Nullable;
+import java.nio.file.Path;
+
+/**
+ * Finds Media Types for resources.
+ *
+ * @author Adam Retter
+ */
+public interface MediaTypeResolver {
+
+ /**
+ * Resolve the Media Type for the filename.
+ *
+ * @param path the Path containing the filename.
+ *
+ * @return The MediaType for the filename, or null if there is no known or configured media type
+ */
+ @Nullable MediaType fromFileName(@Nullable final Path path);
+
+ /**
+ * Resolve the MediaType for the filename.
+ *
+ * @param path the file path containing the filename.
+ *
+ * @return The MediaType for the filename, or null if there is no known or configured media type.
+ */
+ @Nullable MediaType fromFileName(@Nullable final String path);
+
+ /**
+ * Resolve the MediaType from the name/identifier
+ * of the media type.
+ *
+ * @param mediaType the name/identifier of the media type.
+ *
+ * @return The MediaType for the name/identifier, or null if the media type is unknown.
+ */
+ @Nullable MediaType fromString(@Nullable final String mediaType);
+
+ /**
+ * Returns the MediaType to be used for
+ * unknown types of resources.
+ *
+ * This is typically used as a catch-all.
+ *
+ * @return the MediaType to use for unknown
+ * types of resources.
+ */
+ MediaType forUnknown();
+
+ /**
+ * The Instantiation Exception is thrown
+ * if an error occurs when the factory
+ * tries to instantiate a new Media Type Resolver.
+ */
+ class InstantiationException extends Exception {
+ public InstantiationException(final String message) {
+ super(message);
+ }
+
+ public InstantiationException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public InstantiationException(final Throwable cause) {
+ super(cause);
+ }
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaTypeResolverFactory.java b/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaTypeResolverFactory.java
new file mode 100644
index 0000000000..a622df185e
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/MediaTypeResolverFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype;
+
+import javax.annotation.Nullable;
+import java.nio.file.Path;
+import xyz.elemental.mediatype.MediaTypeResolver.InstantiationException;
+
+/**
+ * Factory for instantiating Media Type Resolvers.
+ *
+ * @author Adam Retter
+ */
+public interface MediaTypeResolverFactory {
+
+ /**
+ * Instantiate a new Media Type Resolver.
+ *
+ * @return a new Media Type Resolver.
+ *
+ * @throws InstantiationException if an error occurs
+ * whilst instantiating the MediaTypeResolver.
+ */
+ MediaTypeResolver newMediaTypeResolver()
+ throws InstantiationException;
+
+ /**
+ * Instantiate a new Media Type Resolver.
+ *
+ * @param configDirs paths to directories which contain configuration
+ * files for the media type resolver.
+ *
+ * @return a new Media Type Resolver.
+ *
+ * @throws InstantiationException if an error occurs
+ * whilst instantiating the MediaTypeResolver.
+ */
+ MediaTypeResolver newMediaTypeResolver(@Nullable final Path... configDirs)
+ throws InstantiationException;
+
+}
diff --git a/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/StorageType.java b/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/StorageType.java
new file mode 100644
index 0000000000..01282650c0
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-api/src/main/java/xyz/elemental/mediatype/StorageType.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype;
+
+import javax.annotation.Nullable;
+
+/**
+ * Types of database storage to use for resources of various Media Type.
+ *
+ * @author Adam Retter
+ */
+public enum StorageType {
+ /**
+ * Native XML document storage within the database.
+ */
+ XML,
+
+ /**
+ * Binary document storage within the database.
+ */
+ BINARY;
+
+ /**
+ * Get a StorageType by its name.
+ * Similar to {@link #valueOf(String)} but ignores
+ * cases sensitivity.
+ *
+ * @param name the name of the StorageType
+ * @return the StorageType
+ *
+ * @throws IllegalArgumentException if the name is unknown
+ */
+ public static StorageType fromName(final String name) {
+ final StorageType storageType = lookup(name);
+ if (storageType != null) {
+ return storageType;
+ }
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Get a StorageType by its name.
+ * Similar to {@link #fromName(String)} but
+ * if no Storage Type matches the {@code name}
+ * then the Storage Type for Unknown resources
+ * is returned.
+ *
+ * @param name the name of the StorageType
+ * @return the StorageType for the name, or the Storage
+ * Type for Unknown resources as returned by {@link #forUnknown()}.
+ */
+ public static StorageType fromNameOrDefault(final String name) {
+ final StorageType storageType = lookup(name);
+ if (storageType != null) {
+ return storageType;
+ }
+ return forUnknown();
+ }
+
+ /**
+ * Get a StorageType by its name.
+ * Similar to {@link #valueOf(String)} but ignores
+ * cases sensitivity.
+ *
+ * @param name the name of the StorageType
+ * @return the StorageType or null if there is
+ * no StorageType for the provided name.
+ */
+ private static @Nullable StorageType lookup(String name) {
+ name = name.toUpperCase();
+ for (final StorageType storageType : StorageType.values()) {
+ if (storageType.name().equals(name)) {
+ return storageType;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the StorageType to be used for
+ * unknown types of resources.
+ *
+ * This is typically used as a catch-all.
+ *
+ * @return the StorageType to use for unknown
+ * types of resources.
+ */
+ public static StorageType forUnknown() {
+ return BINARY;
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/pom.xml b/elemental-media-type/elemental-media-type-impl/pom.xml
new file mode 100644
index 0000000000..51388c58a6
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/pom.xml
@@ -0,0 +1,208 @@
+
+
+
+ 4.0.0
+
+
+ xyz.elemental
+ elemental-media-type
+ 7.5.0-SNAPSHOT
+ ..
+
+
+ elemental-media-type-impl
+
+ Elemental Internet Media Type Resolver Implementation
+ Internet Media Type Implementation for Elemental
+
+
+ scm:git:https://github.com/evolvedbinary/elemental.git
+ scm:git:https://github.com/evolvedbinary/elemental.git
+ scm:git:https://github.com/evolvedbinary/elemental.git
+
+
+
+ 2.4.65+1.0.1
+
+
+
+
+ xyz.elemental
+ elemental-media-type-api
+ ${project.version}
+
+
+
+ com.google.code.findbugs
+ jsr305
+
+
+
+ net.jcip
+ jcip-annotations
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ org.slf4j
+ slf4j-simple
+ ${slf4j.version}
+ test
+
+
+
+ io.lacuna
+ bifurcan
+
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+ runtime
+
+
+
+ jakarta.activation
+ jakarta.activation-api
+
+
+
+ org.eclipse.angus
+ angus-activation
+
+
+
+ com.evolvedbinary.thirdparty.org.apache.httpd
+ apache-httpd-mime-types
+ ${httpd.mime-types.version}
+ runtime
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+
+
+
+
+
+ com.mycila
+ license-maven-plugin
+
+
+ SCRIPT_STYLE
+
+
+
+ ${project.parent.relativePath}/../elemental-parent/FDB-backport-to-EDB-LGPL-21-ONLY-license.template.txt
+
+
+
+
+
+
+ org.jvnet.jaxb
+ jaxb-maven-plugin
+
+ src/main/xjb
+ src/main/xsd
+
+
+
+ generate-jaxb-objects
+
+ generate
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ analyze
+
+ analyze-only
+
+
+ true
+
+
+ org.glassfish.jaxb:jaxb-runtime:jar:${jaxb.impl.version}
+
+ com.evolvedbinary.thirdparty.org.apache.httpd:apache-httpd-mime-types:jar:${httpd.mime-types.version}
+
+
+
+ net.sf.xmldb-org:xmldb-api:jar
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+
+ ${project.build.directory}/generated-sources/xjc/**
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/ApplicationMimetypesFileTypeMap.java b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/ApplicationMimetypesFileTypeMap.java
new file mode 100644
index 0000000000..0a75879a47
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/ApplicationMimetypesFileTypeMap.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype.impl;
+
+import io.lacuna.bifurcan.IList;
+import io.lacuna.bifurcan.LinearList;
+import jakarta.activation.MimeTypeEntry;
+import jakarta.activation.MimeTypeRegistry;
+import jakarta.activation.MimetypesFileTypeMap;
+import org.eclipse.angus.activation.MimeTypeFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+
+/**
+ * An implementation of {@link jakarta.activation.FileTypeMap} which
+ * extends {@link jakarta.activation.MimetypesFileTypeMap} to also
+ * read from an application specific file.
+ *
+ *
MIME types file search order
+ * The ApplicationMimetypesFileTypeMap looks in various places in the user's
+ * system for MIME types file entries. When requests are made
+ * to search for MIME types in the ApplicationMimetypesFileTypeMap, it searches
+ * MIME types files in the following order:
+ *
+ * - Programmatically added entries to the ApplicationMimetypesFileTypeMap instance.
+ * - The file
.jakarta.mime.types in the user's home directory.
+ * - The file
.mime.types in the user's home directory.
+ * - The file
jakarta.mime.types from within the user's home directory:
+ *
+ * - Linux/Unix: $XDG_DATA_HOME/jakarta.mime.types If $XDG_DATA_HOME is not set then, ~/.local/share/jakarta.mime.types
+ * - macOS: $XDG_DATA_HOME/jakarta.mime.types. If $XDG_DATA_HOME is not set then, ~/Library/Application Support/jakarta.mime.types
+ * - Windows: %APPDATA%/jakarta.mime.types. If %APPDATA% is not set then, %USERPROFILE%/AppData/Local/jakarta.mime.types
+ *
+ *
+ * - One or more files named
jakarta.mime.types in the application's config directory(s).
+ * - One or more files named
mime.types in the application's config directory(s).
+ * - The file
jakarta.mime.types on the classpath in the package xyz.elemental.mediatype.
+ * - The file
mime.types on the classpath in the package xyz.elemental.mediatype.
+ * - The file
jakarta.mime.types in the Java runtime.
+ * - The file
mime.types in the Java runtime.
+ * - The file or resources named
META-INF/jakarta.mime.types.
+ * - The file or resources named
META-INF/mime.types.
+ * - The file or resource named
META-INF/jakarta.mimetypes.default (usually found only in the activation.jar file).
+ * - The file or resource named
META-INF/mimetypes.default (usually found only in the activation.jar file).
+ *
+ *
+ * (The current implementation looks for the jakarta.mime.types and mime.types files
+ * in the Java runtime in the directory java.home/conf
+ * if it exists, and otherwise in the directory
+ * java.home/lib, where java.home is the value
+ * of the "java.home" System property. Note that the "conf" directory was
+ * introduced in JDK 9.)
+ *
+ * See {@link MimetypesFileTypeMap} for further information.
+ *
+ * @author Adam Retter
+ */
+public class ApplicationMimetypesFileTypeMap extends MimetypesFileTypeMap {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ApplicationMimetypesFileTypeMap.class);
+
+ private static final String JAKARTA_MIME_TYPES_FILENAME = "jakarta.mime.types";
+ private static final String LEGACY_MIME_TYPES_FILENAME = "mime.types";
+
+ public ApplicationMimetypesFileTypeMap(@Nullable final Path... configDirs) {
+ final Vector dbv = new Vector<>(6); // usually 6 or fewer databases
+ @Nullable MimeTypeRegistry mf;
+ dbv.add(null); // place holder for PROG entry
+
+ @Nullable final Method loadFileMethod = getLoadFileMethod();
+ if (loadFileMethod != null) {
+
+ LOG.trace("MimetypesFileTypeMap: load HOME");
+ try {
+ final String user_home = System.getProperty("user.home");
+
+ if (user_home != null) {
+ String path = user_home + File.separator + "." + JAKARTA_MIME_TYPES_FILENAME;
+ mf = loadFileRefl(loadFileMethod, path);
+ if (mf != null) {
+ dbv.add(mf);
+ }
+
+ path = user_home + File.separator + "." + LEGACY_MIME_TYPES_FILENAME;
+ mf = loadFileRefl(loadFileMethod, path);
+ if (mf != null) {
+ dbv.add(mf);
+ }
+ }
+ } catch (final SecurityException ex) {
+ // no-op
+ }
+
+ LOG.trace("MimetypesFileTypeMap: load HOME DATA");
+ try {
+ @Nullable final Path userDataFolder = PathUtil.getUserDataFolder();
+
+ if (userDataFolder != null) {
+ String path = userDataFolder.resolve("." + JAKARTA_MIME_TYPES_FILENAME).toAbsolutePath().toString();
+ mf = loadFileRefl(loadFileMethod, path);
+ if (mf != null) {
+ dbv.add(mf);
+ }
+
+ path = userDataFolder.resolve("." + LEGACY_MIME_TYPES_FILENAME).toAbsolutePath().toString();
+ mf = loadFileRefl(loadFileMethod, path);
+ if (mf != null) {
+ dbv.add(mf);
+ }
+ }
+ } catch (final SecurityException ex) {
+ // no-op
+ }
+
+ LOG.trace("ApplicationMimetypesFileTypeMap: load application");
+ if (configDirs != null) {
+ for (final Path configDir : configDirs) {
+ boolean found = false;
+ final String[] filenames = new String[]{JAKARTA_MIME_TYPES_FILENAME, LEGACY_MIME_TYPES_FILENAME};
+ for (final String filename : filenames) {
+
+ final Path mimeTypesPath = configDir.resolve(filename);
+ if (!Files.exists(mimeTypesPath)) {
+ LOG.trace("No custom {} found at: {}, skipping...", filename, mimeTypesPath.toAbsolutePath());
+ }
+
+ mf = loadFileRefl(loadFileMethod, mimeTypesPath.toAbsolutePath().toString());
+ if (mf != null) {
+ dbv.add(mf);
+ found = true;
+ }
+ }
+ if (!found) {
+ LOG.warn("Could not find Media Types file named {} or {} in: {}, skipping...", JAKARTA_MIME_TYPES_FILENAME, LEGACY_MIME_TYPES_FILENAME, configDir.toAbsolutePath());
+ }
+ }
+ }
+ }
+
+ LOG.trace("ApplicationMimetypesFileTypeMap: load classpath from xyz.elemental.mediatype");
+ @Nullable final Method loadAllResourcesMethod = getLoadAllResourcesMethod();
+ if (loadAllResourcesMethod != null) {
+ loadAllResourcesRefl(loadAllResourcesMethod, dbv, new String[] {
+ "xyz/elemental/mediatype/" + JAKARTA_MIME_TYPES_FILENAME,
+ "xyz/elemental/mediatype/" + LEGACY_MIME_TYPES_FILENAME
+ });
+ }
+
+ if (loadFileMethod != null) {
+ LOG.trace("MimetypesFileTypeMap: load SYS");
+ try {
+ // check system's home
+ final String confDir = confDirRefl();
+ if (confDir != null) {
+ mf = loadFileRefl(loadFileMethod, confDir + JAKARTA_MIME_TYPES_FILENAME);
+ if (mf != null) {
+ dbv.add(mf);
+ }
+
+ mf = loadFileRefl(loadFileMethod, confDir + LEGACY_MIME_TYPES_FILENAME);
+ if (mf != null) {
+ dbv.add(mf);
+ }
+ }
+ } catch (final SecurityException ex) {
+ // no-op
+ }
+ }
+
+ if (loadAllResourcesMethod != null) {
+ LOG.trace("MimetypesFileTypeMap: load JAR");
+ // load from the app's jar file
+ loadAllResourcesRefl(loadAllResourcesMethod, dbv, new String[] {
+ "META-INF/" + JAKARTA_MIME_TYPES_FILENAME,
+ "META-INF/" + LEGACY_MIME_TYPES_FILENAME
+ });
+ }
+
+ @Nullable final Method loadResourceMethod = getLoadResourceMethod();
+ if (loadResourceMethod != null) {
+ LOG.trace("MimetypesFileTypeMap: load DEF");
+ mf = loadResourceRefl(loadResourceMethod, new String[] {
+ "/META-INF/jakarta.mimetypes.default",
+ "/META-INF/mimetypes.default"
+ });
+ if (mf != null) {
+ dbv.add(mf);
+ }
+ }
+
+ final MimeTypeFile[] DB = new MimeTypeFile[dbv.size()];
+ dbv.copyInto(DB);
+ setDBRefl(DB);
+ }
+
+ private static @Nullable Method getLoadFileMethod() {
+ try {
+ final Method loadFileMethod = MimetypesFileTypeMap.class.getDeclaredMethod("loadFile", String.class);
+ loadFileMethod.setAccessible(true);
+ return loadFileMethod;
+ } catch (final NoSuchMethodException e) {
+ LOG.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ private @Nullable MimeTypeRegistry loadFileRefl(final Method loadFileMethod, final String name) {
+ try {
+ return (MimeTypeRegistry) loadFileMethod.invoke(this, name);
+ } catch (final IllegalAccessException | InvocationTargetException e) {
+ LOG.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ private static @Nullable String confDirRefl() {
+ try {
+ final Field confDirField = MimetypesFileTypeMap.class.getDeclaredField("confDir");
+ confDirField.setAccessible(true);
+ return (String) confDirField.get(null);
+ } catch (final NoSuchFieldException | IllegalAccessException e) {
+ LOG.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ private static @Nullable Method getLoadAllResourcesMethod() {
+ try {
+ final Method loadAllResourcesMethod = MimetypesFileTypeMap.class.getDeclaredMethod("loadAllResources", Vector.class, String[].class);
+ loadAllResourcesMethod.setAccessible(true);
+ return loadAllResourcesMethod;
+ } catch (final NoSuchMethodException e) {
+ LOG.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ @SuppressWarnings("RawUseOfParameterizedType")
+ private void loadAllResourcesRefl(final Method loadAllResourcesMethod, final Vector v, final String[] names) {
+ try {
+ loadAllResourcesMethod.invoke(this, v, (Object) names);
+ } catch (final IllegalAccessException | InvocationTargetException e) {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+
+ private static @Nullable Method getLoadResourceMethod() {
+ try {
+ final Method loadResourceMethod = MimetypesFileTypeMap.class.getDeclaredMethod("loadResource", String[].class);
+ loadResourceMethod.setAccessible(true);
+ return loadResourceMethod;
+ } catch (final NoSuchMethodException e) {
+ LOG.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ private @Nullable MimeTypeRegistry loadResourceRefl(final Method loadResourceMethod, final String[] names) {
+ try {
+ return (MimeTypeFile) loadResourceMethod.invoke(this, (Object) names);
+ } catch (final IllegalAccessException | InvocationTargetException e) {
+ LOG.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ private void setDBRefl(final MimeTypeRegistry[] DB) {
+ try {
+ final Field dbField = MimetypesFileTypeMap.class.getDeclaredField("DB");
+ dbField.setAccessible(true);
+ dbField.set(this, DB);
+ } catch (final NoSuchFieldException | IllegalAccessException e) {
+ LOG.error(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Get all the entries from the MimetypesFileTypeMap.
+ *
+ * @return the entries from the MimetypesFileTypeMap.
+ */
+ @SuppressWarnings("unchecked")
+ IList>> getAllEntries() {
+ final MimeTypeRegistry[] mimeTypeRegistries;
+ try {
+ final Field dbField = MimetypesFileTypeMap.class.getDeclaredField("DB");
+ dbField.setAccessible(true);
+ mimeTypeRegistries = (MimeTypeRegistry[]) dbField.get(this);
+ } catch (final NoSuchFieldException | IllegalAccessException e) {
+ LOG.error(e.getMessage(), e);
+ return null;
+ }
+
+ if (mimeTypeRegistries == null) {
+ return null;
+ }
+
+ final LinearList>> entries = new LinearList<>();
+ final Field typeHashField;
+ try {
+ typeHashField = MimeTypeFile.class.getDeclaredField("type_hash");
+ } catch (final NoSuchFieldException e) {
+ LOG.error(e.getMessage(), e);
+ return null;
+ }
+ typeHashField.setAccessible(true);
+
+ try {
+ for (final MimeTypeRegistry mimeTypeRegistry : mimeTypeRegistries) {
+ if (mimeTypeRegistry != null) {
+ final Hashtable typeHash = (Hashtable) typeHashField.get(mimeTypeRegistry);
+ entries.addLast(typeHash.entrySet());
+ }
+ }
+ } catch (final IllegalAccessException e) {
+ LOG.error("Unable to access type_hash from MimeTypeFile", e);
+ return null;
+ }
+
+ return entries.forked();
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeImpl.java b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeImpl.java
new file mode 100644
index 0000000000..21ac682c9d
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeImpl.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype.impl;
+
+import io.lacuna.bifurcan.LinearSet;
+import net.jcip.annotations.NotThreadSafe;
+import net.jcip.annotations.ThreadSafe;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.StorageType;
+
+import javax.annotation.Nullable;
+
+/**
+ * Immutable implementation of a Media Type.
+ *
+ * @author Adam Retter
+ */
+@ThreadSafe
+public class MediaTypeImpl implements MediaType {
+
+ private final String identifier;
+ @Nullable private final String[] knownFileExtensions;
+ private final StorageType storageType;
+
+ /**
+ * MediaTypeImpl is 100% immutable.
+ *
+ * Instead of calling the constructor you can incrementally
+ * build one via {@link Builder}.
+ */
+ private MediaTypeImpl(final String identifier, @Nullable final String[] knownFileExtensions, final StorageType storageType) {
+ this.identifier = identifier;
+ this.knownFileExtensions = knownFileExtensions;
+ this.storageType = storageType;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public @Nullable String[] getKnownFileExtensions() {
+ return knownFileExtensions;
+ }
+
+ @Override
+ public StorageType getStorageType() {
+ return storageType;
+ }
+
+ /**
+ * Construct a new Media Type.
+ *
+ * @param identifier the Media Type identifier
+ * @param storageType the database storage that should be used for resources of this Media Type
+ *
+ * @return a media type builder.
+ */
+ public static MediaTypeImpl.Builder builder(final String identifier, final StorageType storageType) {
+ return Builder.forMediaType(identifier, storageType);
+ }
+
+ /**
+ * Builder pattern which allows us to
+ * ultimately construct an Immutable MediaTypeImpl.
+ */
+ @NotThreadSafe
+ public static class Builder {
+ private final String identifier;
+ private final StorageType storageType;
+ private final LinearSet knownFileExtensions = new LinearSet<>();
+
+ private Builder(final String identifier, final StorageType storageType) {
+ this.identifier = identifier;
+ this.storageType = storageType;
+ }
+
+ /**
+ * Initiate the build of a MediaTypeImpl.
+ *
+ * @param identifier the Media Type identifier
+ * @param storageType the database storage that should be used for resources of this Media Type
+ */
+ static Builder forMediaType(final String identifier, final StorageType storageType) {
+ return new Builder(identifier, storageType);
+ }
+
+ /**
+ * Add a file extension for the Media Type.
+ *
+ * @param fileExtension a file extension
+ * @return this
+ */
+ public Builder addFileExtension(final String fileExtension) {
+ knownFileExtensions.add(fileExtension);
+ return this;
+ }
+
+ /**
+ * Build the Immutable MediaType.
+ *
+ * @return an immutable MediaType.
+ */
+ public MediaType build() {
+ final String[] aryKnownFileExtensions = knownFileExtensions.size() > 0 ? knownFileExtensions.toArray(size -> new String[size]) : null;
+ return new MediaTypeImpl(identifier, aryKnownFileExtensions, storageType);
+ }
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeMapper.java b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeMapper.java
new file mode 100644
index 0000000000..cc1786a2b3
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeMapper.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype.impl;
+
+import io.lacuna.bifurcan.IList;
+import io.lacuna.bifurcan.LinearList;
+import net.jcip.annotations.NotThreadSafe;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import xyz.elemental.mediatype.StorageType;
+import xyz.elemental.mediatype.impl.configuration.MediaType;
+import xyz.elemental.mediatype.impl.configuration.MediaTypeMappings;
+import xyz.elemental.mediatype.impl.configuration.Storage;
+
+import javax.annotation.Nullable;
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBException;
+import jakarta.xml.bind.Unmarshaller;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Maps Media Types to database Storage Types.
+ * Mappings file search order.
+ * The MediaTypeMapper looks in various places in the user's
+ * system for media type mappings files. When requests are made
+ * to resolve media types to storage types, it searches
+ * mappings types files in the following order:
+ *
+ * - The file
media-type-mappings.xml from within the user's home directory:
+ *
+ * - Linux/Unix: $XDG_CONFIG_HOME/elemental/media-type-mappings.xml. If $XDG_CONFIG_HOME is not set then, ~/.config/elemental/media-type-mappings.xml
+ * - macOS: $XDG_CONFIG_HOME/elemental/media-type-mappings.xml. If $XDG_CONFIG_HOME is not set then, ~/Library/Preferences/xyz.elemental/media-type-mappings.xml
+ * - Windows: %APPDATA%/Elemental/media-type-mappings.xml. If %APPDATA% is not set then, %USERPROFILE%/AppData/Local/Elemental/media-type-mappings.xml
+ *
+ *
+ * - One or more files named
media-type-mappings.xml in the Application's config directory(s).
+ * - The file
media-type-mappings.xml on the classpath in the package xyz.elemental.mediatype.
+ *
+ *
+ * @author Adam Retter
+ */
+@NotThreadSafe
+public class MediaTypeMapper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MediaTypeMapper.class);
+
+ private static final String MEDIA_TYPE_MAPPINGS_FILENAME = "media-type-mappings.xml";
+
+ private final Function[] matchers;
+
+ public MediaTypeMapper(@Nullable final Path... configDirs) {
+ final IList mappingsFileSources = getMappingsFileSources(configDirs);
+ this.matchers = loadMatchers(mappingsFileSources);
+ }
+
+ private static IList getMappingsFileSources(final Path... configDirs) {
+ final LinearList mappingsFileSources = new LinearList<>();
+
+ LOG.trace("MediaTypeMapper: load HOME");
+ @Nullable final Path userConfigFolder = PathUtil.getUserConfigFolder();
+ if (userConfigFolder != null) {
+ final Path mappingsFile = userConfigFolder.resolve(MEDIA_TYPE_MAPPINGS_FILENAME);
+ if (!Files.exists(mappingsFile)) {
+ LOG.trace("No media-type-mappings.xml found at: {}, skipping...", mappingsFile.toAbsolutePath());
+ } else {
+ mappingsFileSources.addLast(new MappingsFileSource(mappingsFile));
+ }
+ }
+
+ LOG.trace("MediaTypeMapper: load application");
+ if (configDirs != null) {
+ for (final Path configDir : configDirs) {
+ final Path mappingsFile = configDir.resolve(MEDIA_TYPE_MAPPINGS_FILENAME);
+ if (!Files.exists(mappingsFile)) {
+ LOG.warn("No custom media-type-mappings.xml found at: {}, skipping...", mappingsFile.toAbsolutePath());
+ } else {
+ mappingsFileSources.addLast(new MappingsFileSource(mappingsFile));
+ }
+ }
+ }
+
+ LOG.trace("ApplicationMimetypesFileTypeMap: load classpath from xyz.elemental.mediatype");
+ final String classPathLocationStr = "xyz/elemental/mediatype/" + MEDIA_TYPE_MAPPINGS_FILENAME;
+ @Nullable final URL url = MediaTypeMapper.class.getClassLoader().getResource(classPathLocationStr);
+ if (url == null) {
+ LOG.trace("No media-type-mappings.xml found on classpath from xyz.elemental.mediatype, skipping...");
+ } else {
+ final InputStream is = MediaTypeMapper.class.getClassLoader().getResourceAsStream(classPathLocationStr);
+ mappingsFileSources.addLast(new MappingsFileSource(url.toString(), is));
+ }
+
+ return mappingsFileSources.forked();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Function[] loadMatchers(final IList mappingsFileSources) {
+ try {
+ assert (!mappingsFileSources.isLinear());
+
+ final JAXBContext context;
+ final Unmarshaller unmarshaller;
+ try {
+ context = JAXBContext.newInstance(MediaTypeMappings.class);
+ unmarshaller = context.createUnmarshaller();
+ } catch (final JAXBException e) {
+ LOG.error("Unable to instantiate JAXB Unmarshaller: {}", e.getMessage(), e);
+ return new Function[0];
+ }
+
+ final LinearList> matchersList = new LinearList<>();
+ for (final MappingsFileSource mappingsFileSource : mappingsFileSources) {
+ if (mappingsFileSource.path != null && !Files.exists(mappingsFileSource.path)) {
+ LOG.warn("Mappings path {} does not exist, skipping...", mappingsFileSource.path);
+ continue;
+ }
+
+ try {
+ final MediaTypeMappings mappings;
+ if (mappingsFileSource.path != null) {
+ mappings = (MediaTypeMappings) unmarshaller.unmarshal(mappingsFileSource.path.toUri().toURL());
+ } else {
+ mappings = (MediaTypeMappings) unmarshaller.unmarshal(mappingsFileSource.is);
+ }
+ if (mappings == null || mappings.getStorage() == null || mappings.getStorage().isEmpty()) {
+ LOG.error("No mappings found in {} skipping...", mappingsFileSource.location);
+ continue;
+ }
+
+ for (final Storage storage : mappings.getStorage()) {
+ for (final MediaType mediaType : storage.getMediaType()) {
+
+ final StorageType storageType = toStorageType(storage.getType());
+ final Function matcher;
+ switch (mediaType.getMatch()) {
+ case STARTS_WITH:
+ matcher = identifier -> {
+ if (identifier.startsWith(mediaType.getValue())) {
+ return storageType;
+ } else {
+ return null;
+ }
+ };
+ break;
+
+ case FULL:
+ matcher = identifier -> {
+ if (identifier.equals(mediaType.getValue())) {
+ return storageType;
+ } else {
+ return null;
+ }
+ };
+ break;
+
+ case PATTERN:
+ final Pattern pattern = Pattern.compile(mediaType.getValue());
+ final Matcher patternMatcher = pattern.matcher("");
+ matcher = identifier -> {
+ patternMatcher.reset(identifier);
+ if (patternMatcher.matches()) {
+ return storageType;
+ } else {
+ return null;
+ }
+ };
+ break;
+
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ matchersList.addLast(matcher);
+ }
+ }
+
+ } catch (final MalformedURLException | JAXBException e) {
+ @Nullable String message = e.getMessage();
+ if (message == null) {
+ @Nullable final Throwable cause = e.getCause();
+ if (cause != null) {
+ message = cause.getMessage();
+ }
+ }
+ LOG.error("Skipping {} due to error: {}", mappingsFileSource.location, message, e);
+ }
+ }
+
+ return matchersList.toArray(Function[]::new);
+
+ } finally {
+ for (final MappingsFileSource mappingsFileSource : mappingsFileSources) {
+ if (mappingsFileSource.is != null) {
+ try {
+ mappingsFileSource.is.close();
+ } catch (final IOException e) {
+ LOG.warn("Unable to close mappings file source: {} ", mappingsFileSource.location, e);
+ }
+ }
+ }
+ }
+ }
+
+ private static StorageType toStorageType(final xyz.elemental.mediatype.impl.configuration.StorageType type) {
+ switch (type) {
+ case XML:
+ return StorageType.XML;
+
+ case BINARY:
+ return StorageType.BINARY;
+
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Given a Media Type identifier try and resolve its Storage Type.
+ *
+ * @param mediaTypeIdentifier the identifier of the Media Type.
+ *
+ * @return the Storage Type that should be used for the Media Type,
+ * or {@link StorageType#forUnknown()} if the storage type could not be resolved.
+ */
+ public StorageType resolveStorageType(final String mediaTypeIdentifier) {
+ return resolveStorageType(mediaTypeIdentifier, StorageType.forUnknown());
+ }
+
+ /**
+ * Given a Media Type identifier try and resolve its Storage Type.
+ *
+ * @param mediaTypeIdentifier the identifier of the Media Type.
+ * @param defaultStorageType the default Storage Type to return if a Storage Type cannot
+ * be resolved for the Media Type identifier.
+ *
+ * @return the Storage Type that should be used for the Media Type, or {@link StorageType#forUnknown()} if the storage type could not be found.
+ */
+ public @Nullable StorageType resolveStorageType(final String mediaTypeIdentifier, @Nullable final StorageType defaultStorageType) {
+ for (final Function matcher : matchers) {
+ final StorageType storageType = matcher.apply(mediaTypeIdentifier);
+ if (storageType != null) {
+ return storageType;
+ }
+ }
+
+ return defaultStorageType;
+ }
+
+ private static class MappingsFileSource {
+ private final String location;
+
+ /**
+ * Either {@link #path} or {@link #is} will be set, but never both.
+ */
+ @Nullable private final Path path;
+ @Nullable private final InputStream is;
+
+ private MappingsFileSource(final Path path) {
+ this.location = path.normalize().toAbsolutePath().toString();
+ this.path = path;
+ this.is = null;
+ }
+
+ private MappingsFileSource(final String location, final InputStream is) {
+ this.location = location;
+ this.is = is;
+ this.path = null;
+ }
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeResolverFactoryImpl.java b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeResolverFactoryImpl.java
new file mode 100644
index 0000000000..016a73f8e2
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeResolverFactoryImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype.impl;
+
+import xyz.elemental.mediatype.MediaTypeResolver;
+import xyz.elemental.mediatype.MediaTypeResolverFactory;
+
+import javax.annotation.Nullable;
+import java.nio.file.Path;
+
+/**
+ * Implementation of a Media Type Resolver Factory for
+ * constructing {@link MediaTypeResolverImpl} instances.
+ *
+ * @author Adam Retter
+ */
+public class MediaTypeResolverFactoryImpl implements MediaTypeResolverFactory {
+
+ public MediaTypeResolverFactoryImpl() {
+ }
+
+ @Override
+ public MediaTypeResolver newMediaTypeResolver() {
+ return newMediaTypeResolver((Path[]) null);
+ }
+
+ @Override
+ public MediaTypeResolver newMediaTypeResolver(@Nullable final Path... configDirs) {
+ final ApplicationMimetypesFileTypeMap mimetypesFileTypeMap = new ApplicationMimetypesFileTypeMap(
+ configDirs);
+ final MediaTypeMapper mediaTypeMapper = new MediaTypeMapper(configDirs);
+ return new MediaTypeResolverImpl(mimetypesFileTypeMap, mediaTypeMapper);
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeResolverImpl.java b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeResolverImpl.java
new file mode 100644
index 0000000000..cf654f90a4
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeResolverImpl.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype.impl;
+
+import io.lacuna.bifurcan.IList;
+import io.lacuna.bifurcan.LinearMap;
+import jakarta.activation.MimeTypeEntry;
+import jakarta.activation.MimetypesFileTypeMap;
+import net.jcip.annotations.ThreadSafe;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeResolver;
+import xyz.elemental.mediatype.StorageType;
+
+import javax.annotation.Nullable;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Set;
+
+import static xyz.elemental.mediatype.MediaType.APPLICATION_OCTET_STREAM;
+
+/**
+ * Implementation of a Media Type Resolver.
+ *
+ * Sources the mappings between Media Types and File Extensions
+ * from a {@link MimetypesFileTypeMap}, and then further
+ * maps those onto database storage using a {@link MediaTypeMapper}.
+ *
+ * @author Adam Retter
+ */
+@ThreadSafe
+public class MediaTypeResolverImpl implements MediaTypeResolver {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MediaTypeResolverImpl.class);
+
+ private final io.lacuna.bifurcan.IMap extensionsIndex;
+ private final io.lacuna.bifurcan.IMap identifiersIndex;
+
+ private final MediaType defaultMediaType;
+
+ public MediaTypeResolverImpl(final ApplicationMimetypesFileTypeMap fileTypeMap, final MediaTypeMapper mediaTypeMapper) {
+ final IList>> allEntries = fileTypeMap.getAllEntries();
+ if (allEntries == null) {
+ LOG.warn("Could not load file type maps. No mime types are known to the system!");
+ this.extensionsIndex = io.lacuna.bifurcan.Map.empty();
+ this.identifiersIndex = io.lacuna.bifurcan.Map.empty();
+ this.defaultMediaType = null;
+ return;
+ }
+ assert(!allEntries.isLinear());
+
+ final LinearMap mutExtensionsIndex = new LinearMap<>();
+ final LinearMap mutIdentifiersIndex = new LinearMap<>();
+
+ for (final Set> entrySet : allEntries) {
+ for (final Map.Entry entry : entrySet) {
+ final String fileExtension = entry.getKey().toLowerCase();
+ final String identifier = entry.getValue().getMIMEType().toLowerCase();
+
+ MediaTypeImpl.Builder mediaTypeBuilder = mutExtensionsIndex.get(fileExtension, null);
+ if (mediaTypeBuilder == null) {
+ // not present in extensionsIndex
+
+ mediaTypeBuilder = mutIdentifiersIndex.get(identifier, null);
+ if (mediaTypeBuilder == null) {
+
+ // not present in identifiersIndex or extensionsIndex
+ mediaTypeBuilder = MediaTypeImpl.Builder
+ .forMediaType(identifier, mediaTypeMapper.resolveStorageType(identifier))
+ .addFileExtension(fileExtension);
+
+ mutExtensionsIndex.put(fileExtension, mediaTypeBuilder);
+ mutIdentifiersIndex.put(identifier, mediaTypeBuilder);
+
+ } else {
+
+ // present in identifiersIndex, but not extensionsIndex
+ mediaTypeBuilder.addFileExtension(fileExtension);
+ mutExtensionsIndex.put(fileExtension, mediaTypeBuilder);
+ }
+ }
+ }
+ }
+
+ this.extensionsIndex = mutExtensionsIndex.mapValues((k, v) -> v.build()).forked();
+ this.identifiersIndex = mutIdentifiersIndex.mapValues((k, v) -> v.build()).forked();
+
+ assert(!extensionsIndex.isLinear());
+ assert(!identifiersIndex.isLinear());
+
+ this.defaultMediaType = identifiersIndex.get(APPLICATION_OCTET_STREAM)
+ .orElseGet(() -> MediaTypeImpl.Builder.forMediaType(APPLICATION_OCTET_STREAM, StorageType.BINARY).build());
+ }
+
+ @Override
+ public @Nullable MediaType fromFileName(@Nullable final Path path) {
+ if (path == null) {
+ return null;
+ }
+ return fromFileNameImpl(path.getFileName().toString());
+ }
+
+ @Override
+ public @Nullable MediaType fromFileName(@Nullable String path) {
+ if (path == null) {
+ return null;
+ }
+
+ // if this is a path, just take the last segment i.e. the filename
+ int pathSepIdx = -1;
+ if ((pathSepIdx = path.lastIndexOf('/')) > -1) {
+ path = path.substring(pathSepIdx + 1);
+ } else if ((pathSepIdx = path.lastIndexOf('\\')) > -1) {
+ path = path.substring(pathSepIdx + 1);
+ }
+
+ return fromFileNameImpl(path);
+ }
+
+ private @Nullable MediaType fromFileNameImpl(final String fileName) {
+ final int idx = fileName.lastIndexOf("."); // period index
+ if (idx == -1) {
+ return null;
+ }
+
+ final String extension = fileName.substring(idx + 1);
+ if (extension.isEmpty()) {
+ return null;
+ }
+
+ return extensionsIndex.get(extension.toLowerCase(), null);
+ }
+
+ @Override
+ public @Nullable MediaType fromString(@Nullable final String mediaType) {
+ if (mediaType == null) {
+ return null;
+ }
+
+ return identifiersIndex.get(mediaType.toLowerCase(), null);
+ }
+
+ @Override
+ public MediaType forUnknown() {
+ return defaultMediaType;
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/PathUtil.java b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/PathUtil.java
new file mode 100644
index 0000000000..de54559a70
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/PathUtil.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype.impl;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static xyz.elemental.mediatype.impl.StringUtil.emptyStringAsNull;
+
+/**
+ * Utilities for working with Paths.
+ *
+ * @author Adam Retter
+ */
+class PathUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PathUtil.class);
+
+ /**
+ * Gets the config directory from the user's home folder.
+ *
+ * @return One of the following:
+ *
+ * - Linux/Unix: $XDG_CONFIG_HOME/elemental. If $XDG_CONFIG_HOME is not set then, ~/.config/elemental
+ * - macOS: $XDG_CONFIG_HOME/elemental. If $XDG_CONFIG_HOME is not set then, ~/Library/Preferences/xyz.elemental
+ * - Windows: %APPDATA%/Elemental. If %APPDATA% is not set then, %USERPROFILE%/AppData/Local/Elemental
+ *
+ * or null if the environment variables or home folder cannot be resolved.
+ */
+ static @Nullable Path getUserConfigFolder() {
+ final String osName = System.getProperty("os.name").toLowerCase();
+
+ if (osName.startsWith("windows")) {
+ // Windows
+ @Nullable String appDataPath = emptyStringAsNull(System.getenv("APPDATA"));
+
+ if (appDataPath == null) {
+ @Nullable String userProfilePath = emptyStringAsNull(System.getProperty("user.home"));
+ if (userProfilePath == null) {
+ LOG.warn("Unable to find environment variables %APPDATA% or %USERPROFILE%");
+ } else {
+ appDataPath = userProfilePath + "\\AppData\\Local";
+ }
+ }
+
+ if (appDataPath != null) {
+ return Paths.get(appDataPath, "Elemental");
+ }
+
+ } else {
+ @Nullable final String xdgConfigPath = emptyStringAsNull(System.getenv("XDG_CONFIG_HOME"));
+ if (xdgConfigPath != null) {
+ return Paths.get(xdgConfigPath, "elemental");
+ }
+
+ @Nullable final String homePath = System.getProperty("user.home");
+ if (homePath == null) {
+ LOG.warn("Unable to find environment variable %HOME%");
+ } else {
+ if (osName.startsWith("mac os x")) {
+ // macOS
+ return Paths.get(homePath, "Library", "Preferences", "xyz.elemental");
+
+ } else {
+ // Linux/Unix (or anything else)
+ return Paths.get(homePath, ".config", "elemental");
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the data directory from the user's home folder.
+ *
+ * @return One of the following:
+ *
+ * - Linux/Unix: $XDG_DATA_HOME If $XDG_DATA_HOME is not set then, ~/.local/share
+ * - macOS: $XDG_DATA_HOME. If $XDG_DATA_HOME is not set then, ~/Library/Application Support
+ * - Windows: %APPDATA%. If %APPDATA% is not set then, %USERPROFILE%/AppData/Local
+ *
+ * or null if the environment variables or home folder cannot be resolved.
+ */
+ static @Nullable Path getUserDataFolder() {
+ final String osName = System.getProperty("os.name").toLowerCase();
+
+ if (osName.startsWith("windows")) {
+ // Windows
+ @Nullable String appDataPath = emptyStringAsNull(System.getenv("APPDATA"));
+
+ if (appDataPath == null) {
+ @Nullable String userProfilePath = emptyStringAsNull(System.getProperty("user.home"));
+ if (userProfilePath == null) {
+ LOG.warn("Unable to find environment variables %APPDATA% or %USERPROFILE%");
+ } else {
+ appDataPath = userProfilePath + "\\AppData\\Local";
+ }
+ }
+
+ if (appDataPath != null) {
+ return Paths.get(appDataPath);
+ }
+
+ } else {
+ @Nullable final String xdgConfigPath = emptyStringAsNull(System.getenv("XDG_DATA_HOME"));
+ if (xdgConfigPath != null) {
+ return Paths.get(xdgConfigPath);
+ }
+
+ @Nullable final String homePath = System.getProperty("user.home");
+ if (homePath == null) {
+ LOG.warn("Unable to find environment variable %HOME%");
+ } else {
+ if (osName.startsWith("mac os x")) {
+ // macOS
+ return Paths.get(homePath, "Library", "Application Support");
+
+ } else {
+ // Linux/Unix (or anything else)
+ return Paths.get(homePath, ".local", "share");
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/StringUtil.java b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/StringUtil.java
new file mode 100644
index 0000000000..fb28ac87f2
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/StringUtil.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype.impl;
+
+import javax.annotation.Nullable;
+
+/**
+ * Utilities for working with Strings.
+ *
+ * @author Adam Retter
+ */
+class StringUtil {
+
+ static @Nullable String emptyStringAsNull(@Nullable String str) {
+ if (str != null) {
+ str = str.trim();
+ if (str.isEmpty()) {
+ str = null;
+ }
+ }
+ return str;
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/resources/META-INF/services/xyz.elemental.mediatype.MediaTypeResolverFactory b/elemental-media-type/elemental-media-type-impl/src/main/resources/META-INF/services/xyz.elemental.mediatype.MediaTypeResolverFactory
new file mode 100644
index 0000000000..cf19bc412e
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/resources/META-INF/services/xyz.elemental.mediatype.MediaTypeResolverFactory
@@ -0,0 +1 @@
+xyz.elemental.mediatype.impl.MediaTypeResolverFactoryImpl
\ No newline at end of file
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/xjb/media-type-mappings.xjb b/elemental-media-type/elemental-media-type-impl/src/main/xjb/media-type-mappings.xjb
new file mode 100644
index 0000000000..7df9688282
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/xjb/media-type-mappings.xjb
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/xsd/media-type-mappings.xsd b/elemental-media-type/elemental-media-type-impl/src/main/xsd/media-type-mappings.xsd
new file mode 100644
index 0000000000..254bd9ed38
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/xsd/media-type-mappings.xsd
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+ Maps files of various Media Types to the type of storage
+ that should be used for persisting those files.
+
+
+
+
+
+
+
+
+
+
+
+ Each type of storage should only appear once
+
+
+
+
+
+
+
+
+ The type of persistent storage to use for various Media Types
+
+
+
+
+
+
+
+
+
+
+
+ Matches a Media Type
+
+
+
+
+
+
+
+
+
+
+
+
+ Types of persistent storage
+
+
+
+
+ Native XML document storage within the database
+
+
+
+
+
+
+
+
+ Binary document storage within the database
+
+
+
+
+
+
+
+ Different types of Media Type matching
+
+
+
+
+ Media Type must exactly match the supplied value
+
+
+
+
+ Media Type(s) must start-with the supplied value
+
+
+
+
+ Media Type(s) must match the supplied Java Regular Expression
+
+
+
+
+
+
+
diff --git a/elemental-media-type/elemental-media-type-impl/src/test/java/xyz/elemental/mediatype/impl/MediaTypeResolverImplTest.java b/elemental-media-type/elemental-media-type-impl/src/test/java/xyz/elemental/mediatype/impl/MediaTypeResolverImplTest.java
new file mode 100644
index 0000000000..f90a90d06e
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/test/java/xyz/elemental/mediatype/impl/MediaTypeResolverImplTest.java
@@ -0,0 +1,833 @@
+/*
+ * Copyright (C) 2014, Evolved Binary Ltd
+ *
+ * This file was originally ported from FusionDB to Elemental by
+ * Evolved Binary, for the benefit of the Elemental Open Source community.
+ * Only the ported code as it appears in this file, at the time that
+ * it was contributed to Elemental, was re-licensed under The GNU
+ * Lesser General Public License v2.1 only for use in Elemental.
+ *
+ * This license grant applies only to a snapshot of the code as it
+ * appeared when ported, it does not offer or infer any rights to either
+ * updates of this source code or access to the original source code.
+ *
+ * The GNU Lesser General Public License v2.1 only license follows.
+ *
+ * =====================================================================
+ *
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package xyz.elemental.mediatype.impl;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeResolver;
+import xyz.elemental.mediatype.StorageType;
+
+import javax.annotation.Nullable;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class MediaTypeResolverImplTest {
+
+ // TODO(AR) if an explicit content type is provided, e.g. HTTP PUT, store the mime type with the document data??? what if its not provided, lookup and store, or lookup on retrieval?
+
+ private static MediaTypeMapper MEDIA_TYPE_MAPPER = null;
+ private static MediaTypeResolver DEFAULT_MEDIA_RESOLVER = null;
+ private static MediaTypeResolver APPLICATION_MEDIA_RESOLVER = null;
+
+ @BeforeAll
+ public static void setupMediaResolvers() throws URISyntaxException {
+ @Nullable final URL mediaTypeMappings = MediaTypeResolverImplTest.class.getResource("media-type-mappings.xml");
+ assertNotNull(mediaTypeMappings);
+ final Path configDir = Paths.get(mediaTypeMappings.toURI()).getParent();
+ MEDIA_TYPE_MAPPER = new MediaTypeMapper(configDir);
+
+ final ApplicationMimetypesFileTypeMap defaultMimetypesFileTypeMap = new ApplicationMimetypesFileTypeMap((Path[]) null);
+ DEFAULT_MEDIA_RESOLVER = new MediaTypeResolverImpl(defaultMimetypesFileTypeMap, MEDIA_TYPE_MAPPER);
+
+ APPLICATION_MEDIA_RESOLVER = new MediaTypeResolverFactoryImpl().newMediaTypeResolver(configDir);
+ }
+
+ //
+ @Test
+ public void allResolveAtomExtension() {
+ assertAllResolveFromFileName("something.atom", MediaType.APPLICATION_ATOM, new String[] {"atom"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveCsvExtension() {
+ assertAllResolveFromFileName("something.csv", MediaType.TEXT_CSV, new String[] {"csv"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveDocxExtension() {
+ assertAllResolveFromFileName("something.docx", MediaType.APPLICATION_OPENXML_WORDPROCESSING, new String[] {"docx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveDtdExtension() {
+ assertAllResolveFromFileName("something.dtd", MediaType.APPLICATION_XML_DTD, new String[] {"dtd"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveGifExtension() {
+ assertAllResolveFromFileName("something.gif", MediaType.IMAGE_GIF, new String[] {"gif"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveGmlExtension() {
+ assertAllResolveFromFileName("something.gml", MediaType.APPLICATION_GML, new String[] {"gml"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveHtmExtension() {
+ assertAllResolveFromFileName("something.htm", MediaType.TEXT_HTML, new String[] {"htm", "html"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveHtmlExtension() {
+ assertAllResolveFromFileName("something.html", MediaType.TEXT_HTML, new String[] {"htm", "html"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveJpegExtension() {
+ assertAllResolveFromFileName("something.jpeg", MediaType.IMAGE_JPEG, new String[] {"jpe", "jpg", "jpeg"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveJpgExtension() {
+ assertAllResolveFromFileName("something.jpg", MediaType.IMAGE_JPEG, new String[] {"jpe", "jpg", "jpeg"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveJsExtension() {
+ assertAllResolveFromFileName("something.js", MediaType.TEXT_JAVASCRIPT, new String[] {"js", "mjs"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveJsonExtension() {
+ assertAllResolveFromFileName("something.json", MediaType.APPLICATION_JSON, new String[] {"json"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveMadsExtension() {
+ assertAllResolveFromFileName("something.mads", MediaType.APPLICATION_MADS, new String[] {"mads"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveMetsExtension() {
+ assertAllResolveFromFileName("something.mets", MediaType.APPLICATION_METS, new String[] {"mets"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveModsExtension() {
+ assertAllResolveFromFileName("something.mods", MediaType.APPLICATION_MODS, new String[] {"mods"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveMrcxExtension() {
+ assertAllResolveFromFileName("something.mrcx", MediaType.APPLICATION_MARC, new String[] {"mrcx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveN3Extension() {
+ assertAllResolveFromFileName("something.n3", MediaType.TEXT_N3, new String[] {"n3"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveNcxExtension() {
+ assertAllResolveFromFileName("something.ncx", MediaType.APPLICATION_NCX, new String[] {"ncx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveOdtExtension() {
+ assertAllResolveFromFileName("something.odt", MediaType.APPLICATION_OPENDOCUMENT_TEXT, new String[] {"odt"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveOdpExtension() {
+ assertAllResolveFromFileName("something.odp", MediaType.APPLICATION_OPENDOCUMENT_PRESENTATION, new String[] {"odp"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveOdsExtension() {
+ assertAllResolveFromFileName("something.ods", MediaType.APPLICATION_OPENDOCUMENT_SPREADSHEET, new String[] {"ods"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveOpfExtension() {
+ assertAllResolveFromFileName("something.opf", MediaType.APPLICATION_OEBPS_PACKAGE, new String[] {"opf"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolvePngExtension() {
+ assertAllResolveFromFileName("something.png", MediaType.IMAGE_PNG, new String[] {"png"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolvePptxExtension() {
+ assertAllResolveFromFileName("something.pptx", MediaType.APPLICATION_OPENXML_PRESENTATION, new String[] {"pptx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveRncExtension() {
+ assertAllResolveFromFileName("something.rnc", MediaType.APPLICATION_RELAXNG_COMPACT, new String[] {"rnc"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveRssExtension() {
+ assertAllResolveFromFileName("something.rss", MediaType.APPLICATION_RSS, new String[] {"rss"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveSruExtension() {
+ assertAllResolveFromFileName("something.sru", MediaType.APPLICATION_SRU, new String[] {"sru"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveTtlExtension() {
+ assertAllResolveFromFileName("something.ttl", MediaType.TEXT_TURTLE, new String[] {"ttl"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveTxtExtension() {
+ assertAllResolveFromFileName("something.txt", MediaType.TEXT_PLAIN, new String[] {"txt", "def", "log", "in", "conf", "text", "list"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveWsdlExtension() {
+ assertAllResolveFromFileName("something.wsdl", MediaType.APPLICATION_WSDL, new String[] {"wsdl"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXhtExtension() {
+ assertAllResolveFromFileName("something.xht", MediaType.APPLICATION_XHTML, new String[] {"xht", "xhtml"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXhtmlExtension() {
+ assertAllResolveFromFileName("something.xhtml", MediaType.APPLICATION_XHTML, new String[] {"xht", "xhtml"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXlsxExtension() {
+ assertAllResolveFromFileName("something.xlsx", MediaType.APPLICATION_OPENXML_SPREADSHEET, new String[] {"xlsx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXplExtension() {
+ assertAllResolveFromFileName("something.xpl", MediaType.APPLICATION_XPROC, new String[] {"xpl"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXsltExtension() {
+ assertAllResolveFromFileName("something.xslt", MediaType.APPLICATION_XSLT, new String[] {"xslt"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveAtomIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_ATOM, new String[] {"atom"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveCsvIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.TEXT_CSV, new String[] {"csv"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveDocxIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_OPENXML_WORDPROCESSING, new String[] {"docx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveDtdIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_XML_DTD, new String[] {"dtd"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveGifIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.IMAGE_GIF, new String[] {"gif"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveGmlIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_GML, new String[] {"gml"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveHtmlIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.TEXT_HTML, new String[] {"htm", "html"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveJpegIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.IMAGE_JPEG, new String[] {"jpe", "jpg", "jpeg"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveJsIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.TEXT_JAVASCRIPT, new String[] {"js", "mjs"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveJsonIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_JSON, new String[] {"json"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveMadsIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_MADS, new String[] {"mads"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveMetsIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_METS, new String[] {"mets"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveModsIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_MODS, new String[] {"mods"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveMrcxIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_MARC, new String[] {"mrcx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveN3Identifier() {
+ assertAllResolveFromIdentifier(MediaType.TEXT_N3, new String[] {"n3"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveNcxIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_NCX, new String[] {"ncx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveOdtIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_OPENDOCUMENT_TEXT, new String[] {"odt"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveOdpIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_OPENDOCUMENT_PRESENTATION, new String[] {"odp"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveOdsIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_OPENDOCUMENT_SPREADSHEET, new String[] {"ods"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveOpfIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_OEBPS_PACKAGE, new String[] {"opf"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolvePngIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.IMAGE_PNG, new String[] {"png"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolvePptxIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_OPENXML_PRESENTATION, new String[] {"pptx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveRncIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_RELAXNG_COMPACT, new String[] {"rnc"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveRssIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_RSS, new String[] {"rss"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveSruIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_SRU, new String[] {"sru"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveTtlIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.TEXT_TURTLE, new String[] {"ttl"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveTxtIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.TEXT_PLAIN, new String[] {"txt", "def", "log", "in", "conf", "text", "list"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void allResolveWsdlIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_WSDL, new String[] {"wsdl"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXhtmlIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_XHTML, new String[] {"xht", "xhtml"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXlsxIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_OPENXML_SPREADSHEET, new String[] {"xlsx"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXplIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_XPROC, new String[] {"xpl"}, StorageType.XML);
+ }
+
+ @Test
+ public void allResolveXsltIdentifier() {
+ assertAllResolveFromIdentifier(MediaType.APPLICATION_XSLT, new String[] {"xslt"}, StorageType.XML);
+ }
+ //
+
+
+ //
+ @Test
+ public void defaultResolveRdfExtension() {
+ assertDefaultResolveFromFileName("something.rdf", MediaType.APPLICATION_RDF_XML, new String[] {"rdf"}, StorageType.XML);
+ }
+
+ /**
+ * The Media Type for SVGZ is horribly broken, see: w3c/svgwg/issues/701
+ * So it is overridden in the application's own mime.types file,
+ * see {@link #applicationResolveSvgExtension()}.
+ */
+ @Test
+ public void defaultResolveSvgExtension() {
+ assertDefaultResolveFromFileName("something.svg", MediaType.IMAGE_SVG, new String[] {"svg", "svgz"}, StorageType.XML);
+ }
+
+ /**
+ * The Media Type for SVGZ is horribly broken, see: w3c/svgwg/issues/701
+ * So it is overridden in the application's own mime.types file,
+ * see {@link #applicationResolveSvgzExtension()}.
+ */
+ @Test
+ public void defaultResolveSvgzExtension() {
+ assertDefaultResolveFromFileName("something.svgz", MediaType.IMAGE_SVG, new String[] {"svg", "svgz"}, StorageType.XML);
+ }
+
+ @Test
+ public void defaultResolveTeiExtension() {
+ assertDefaultResolveFromFileName("something.tei", MediaType.APPLICATION_TEI, new String[] {"tei", "teicorpus"}, StorageType.XML);
+ }
+
+ @Test
+ public void defaultResolveTeicorpusExtension() {
+ assertDefaultResolveFromFileName("something.teicorpus", MediaType.APPLICATION_TEI, new String[] {"tei", "teicorpus"}, StorageType.XML);
+ }
+
+ @Test
+ public void defaultResolveXmlExtension() {
+ assertDefaultResolveFromFileName("something.xml", MediaType.APPLICATION_XML, new String[] {"xsl", "xml"}, StorageType.XML);
+ }
+
+ @Test
+ public void defaultResolveXslExtension() {
+ assertDefaultResolveFromFileName("something.xsl", MediaType.APPLICATION_XML, new String[] {"xsl", "xml"}, StorageType.XML);
+ }
+
+ @Test
+ public void defaultResolveRdfIdentifier() {
+ assertDefaultResolveFromIdentifier(MediaType.APPLICATION_RDF_XML, new String[] {"rdf"}, StorageType.XML);
+ }
+
+ /**
+ * The Media Type for SVGZ is horribly broken, see: w3c/svgwg/issues/701
+ * So it is overridden in the application's own mime.types file.
+ */
+ @Test
+ public void defaultResolveSvgIdentifier() {
+ assertDefaultResolveFromIdentifier(MediaType.IMAGE_SVG, new String[] {"svg", "svgz"}, StorageType.XML);
+ }
+
+ @Test
+ public void defaultResolveTeiIdentifier() {
+ assertDefaultResolveFromIdentifier(MediaType.APPLICATION_TEI, new String[] {"tei", "teicorpus"}, StorageType.XML);
+ }
+
+ @Test
+ public void defaultResolveXmlIdentifier() {
+ assertDefaultResolveFromIdentifier(MediaType.APPLICATION_XML, new String[] {"xsl", "xml"}, StorageType.XML);
+ }
+ //
+
+
+ //
+ @Test
+ public void applicationResolveDitaExtension() {
+ assertApplicationResolveFromFileName("something.dita",MediaType.APPLICATION_DITA, new String[] {"dita", "ditamap", "ditaval"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveDitamapExtension() {
+ assertApplicationResolveFromFileName("something.ditamap",MediaType.APPLICATION_DITA, new String[] {"dita", "ditamap", "ditaval"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveDitavalExtension() {
+ assertApplicationResolveFromFileName("something.ditaval",MediaType.APPLICATION_DITA, new String[] {"dita", "ditamap", "ditaval"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveFoExtension() {
+ assertApplicationResolveFromFileName("something.fo", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveNvdlExtension() {
+ assertApplicationResolveFromFileName("something.nvdl", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveOddExtension() {
+ assertApplicationResolveFromFileName("something.odd", MediaType.APPLICATION_TEI, new String[] {"odd", "tei", "teicorpus"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveOwlExtension() {
+ assertApplicationResolveFromFileName("something.owl", MediaType.APPLICATION_RDF_XML, new String[] {"xmp", "owl", "rdf"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveMdExtension() {
+ assertApplicationResolveFromFileName("something.md", MediaType.TEXT_MARKDOWN, new String[] {"md"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveRdfExtension() {
+ assertApplicationResolveFromFileName("something.rdf", MediaType.APPLICATION_RDF_XML, new String[] {"xmp", "owl", "rdf"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveRngExtension() {
+ assertApplicationResolveFromFileName("something.rng", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveSchExtension() {
+ assertApplicationResolveFromFileName("something.sch", MediaType.APPLICATION_SCHEMATRON, new String[] {"sch"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveStxExtension() {
+ assertApplicationResolveFromFileName("something.stx", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveSvgExtension() {
+ assertApplicationResolveFromFileName("something.svg", MediaType.IMAGE_SVG, new String[] {"svg", "svgz"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveSvgzExtension() {
+ assertApplicationResolveFromFileName("something.svgz", MediaType.IMAGE_SVG_GZIP, new String[] {"svg", "svgz"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveTeiExtension() {
+ assertApplicationResolveFromFileName("something.tei", MediaType.APPLICATION_TEI, new String[] {"odd", "tei", "teicorpus"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveTeicorpusExtension() {
+ assertApplicationResolveFromFileName("something.teicorpus", MediaType.APPLICATION_TEI, new String[] {"odd", "tei", "teicorpus"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXarExtension() {
+ assertApplicationResolveFromFileName("something.xar", MediaType.APPLICATION_EXPATH_PACKAGE_ZIP, new String[] {"xar"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveXconfExtension() {
+ assertApplicationResolveFromFileName("something.xconf", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXmiExtension() {
+ assertApplicationResolveFromFileName("something.xmi", MediaType.APPLICATION_XMI, new String[] {"xmi"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXmlExtension() {
+ assertApplicationResolveFromFileName("something.xml", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXmpExtension() {
+ assertApplicationResolveFromFileName("something.xmp", MediaType.APPLICATION_RDF_XML, new String[] {"xmp", "owl", "rdf"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXqExtension() {
+ assertApplicationResolveFromFileName("something.xq", MediaType.APPLICATION_XQUERY, new String[] {"xq", "xql", "xqm", "xquery", "xqws", "xqy"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveXqlExtension() {
+ assertApplicationResolveFromFileName("something.xql", MediaType.APPLICATION_XQUERY, new String[] {"xq", "xql", "xqm", "xquery", "xqws", "xqy"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveXqmExtension() {
+ assertApplicationResolveFromFileName("something.xqm", MediaType.APPLICATION_XQUERY, new String[] {"xq", "xql", "xqm", "xquery", "xqws", "xqy"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveXqueryExtension() {
+ assertApplicationResolveFromFileName("something.xquery", MediaType.APPLICATION_XQUERY, new String[] {"xq", "xql", "xqm", "xquery", "xqws", "xqy"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveXqwsExtension() {
+ assertApplicationResolveFromFileName("something.xqws", MediaType.APPLICATION_XQUERY, new String[] {"xq", "xql", "xqm", "xquery", "xqws", "xqy"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveXqxExtension() {
+ assertApplicationResolveFromFileName("something.xqx", MediaType.APPLICATION_XQUERY_XML, new String[] {"xqx"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXqyExtension() {
+ assertApplicationResolveFromFileName("something.xqy", MediaType.APPLICATION_XQUERY, new String[] {"xq", "xql", "xqm", "xquery", "xqws", "xqy"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveXsdExtension() {
+ assertApplicationResolveFromFileName("something.xsd", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXslExtension() {
+ assertApplicationResolveFromFileName("something.xsl", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveDitaIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.APPLICATION_DITA, new String[] {"dita", "ditamap", "ditaval"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveMdIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.TEXT_MARKDOWN, new String[] {"md"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveRdfIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.APPLICATION_RDF_XML, new String[] {"xmp", "owl", "rdf"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveSchIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.APPLICATION_SCHEMATRON, new String[] {"sch"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveSvgIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.IMAGE_SVG, new String[] {"svg", "svgz"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveSvgzIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.IMAGE_SVG_GZIP, new String[] {"svg", "svgz"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveTeiIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.APPLICATION_TEI, new String[] {"odd", "tei", "teicorpus"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXmiIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.APPLICATION_XMI, new String[] {"xmi"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXmlIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveXqueryIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.APPLICATION_XQUERY, new String[] {"xq", "xql", "xqm", "xquery", "xqws", "xqy"}, StorageType.BINARY);
+ }
+
+ @Test
+ public void applicationResolveXqueryXIdentifier() {
+ assertApplicationResolveFromIdentifier(MediaType.APPLICATION_XQUERY_XML, new String[] {"xqx"}, StorageType.XML);
+ }
+ //
+
+
+ /**
+ * Check that multiple levels of mime.types files
+ * yield correct lookups via. both
+ * ApplicationMimetypesFileTypeMap and MediaTypeResolverImpl.
+ */
+ @Test
+ public void resolveFromCorrectLevel() throws URISyntaxException {
+ @Nullable final URL defaultApplicationMimeTypes = MediaTypeResolverImplTest.class.getResource("mime.types");
+ assertNotNull(defaultApplicationMimeTypes);
+ final Path defaultApplicationTypesConfigDir = Paths.get(defaultApplicationMimeTypes.toURI()).getParent();
+ final String packageNamePath = MediaTypeResolverImplTest.class.getPackage().getName().replace('.', '/');
+
+ @Nullable final URL moreSpecificMimeTypes = MediaTypeResolverImplTest.class.getResource("/" + packageNamePath + "/test/levels/mime.types");
+ assertNotNull(moreSpecificMimeTypes);
+ final Path moreSpecificApplicationTypesConfigDir = Paths.get(moreSpecificMimeTypes.toURI()).getParent();
+
+ // NOTE(AR) moreSpecificApplicationTypesConfigDir is provided first so that it has highest priority
+ final ApplicationMimetypesFileTypeMap mimetypesFileTypeMap = new ApplicationMimetypesFileTypeMap(
+ moreSpecificApplicationTypesConfigDir,
+ defaultApplicationTypesConfigDir);
+
+ assertEquals("test/extensible-markup-language", mimetypesFileTypeMap.getContentType("something.xadam"));
+ assertEquals("test/prs.existdb.collection-config+xml", mimetypesFileTypeMap.getContentType("something.xconf"));
+ assertEquals("test/extensible-markup-language", mimetypesFileTypeMap.getContentType("something.xml"));
+ assertEquals(MediaType.APPLICATION_XML, mimetypesFileTypeMap.getContentType("something.xsd"));
+ assertEquals("test/x.xsl+xml", mimetypesFileTypeMap.getContentType("something.xsl"));
+
+ final MediaTypeResolverImpl specificMediaTypeResolver = new MediaTypeResolverImpl(mimetypesFileTypeMap, MEDIA_TYPE_MAPPER);
+
+ assertResolveFromFileName(specificMediaTypeResolver, "something.xadam", "test/extensible-markup-language", new String[] {"xml", "xadam"}, StorageType.BINARY);
+ assertResolveFromFileName(specificMediaTypeResolver, "something.xconf", "test/prs.existdb.collection-config+xml", new String[] {"xconf"}, StorageType.XML);
+ assertResolveFromFileName(specificMediaTypeResolver, "something.xml", "test/extensible-markup-language", new String[] {"xml", "xadam"}, StorageType.BINARY);
+ assertResolveFromFileName(specificMediaTypeResolver, "something.xsd", MediaType.APPLICATION_XML, new String[] {"nvdl", "stx", "xsd", "fo", "rng"}, StorageType.XML);
+ assertResolveFromFileName(specificMediaTypeResolver, "something.xsl", "test/x.xsl+xml", new String[] {"xsl"}, StorageType.XML);
+
+ assertResolveFromIdentifier(specificMediaTypeResolver, "test/extensible-markup-language", new String[] { "xml", "xadam" }, StorageType.BINARY);
+ assertResolveFromIdentifier(specificMediaTypeResolver, "test/prs.existdb.collection-config+xml", new String[] {"xconf"}, StorageType.XML);
+ assertResolveFromIdentifier(specificMediaTypeResolver, MediaType.APPLICATION_XML, new String[] {"nvdl", "stx", "xsd", "fo", "rng"}, StorageType.XML);
+ assertResolveFromIdentifier(specificMediaTypeResolver, "test/x.xsl+xml", new String[] {"xsl"}, StorageType.XML);
+ }
+
+ //
+ @Test
+ public void allResolveNonExistentExtension() {
+ final String fileName = "something.nonexistent";
+
+ final MediaTypeResolver[] allResolvers = {
+ DEFAULT_MEDIA_RESOLVER,
+ APPLICATION_MEDIA_RESOLVER
+ };
+
+ for (final MediaTypeResolver resolver : allResolvers) {
+ assertNotNull(resolver);
+
+ @Nullable MediaType mediaType = resolver.fromFileName(fileName);
+ assertNull(mediaType);
+ mediaType = resolver.fromFileName(Paths.get(fileName));
+ assertNull(mediaType);
+ }
+ }
+
+ @Test
+ public void allResolveNonExistentIdentifier() {
+ final String identifier = "non/existent";
+
+ final MediaTypeResolver[] allResolvers = {
+ DEFAULT_MEDIA_RESOLVER,
+ APPLICATION_MEDIA_RESOLVER
+ };
+
+ for (final MediaTypeResolver resolver : allResolvers) {
+ assertNotNull(resolver);
+
+ @Nullable MediaType mediaType = resolver.fromString(identifier);
+ assertNull(mediaType);
+ }
+ }
+ //
+
+ private void assertAllResolveFromFileName(final String fileName, final String expectedIdentifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertDefaultResolveFromFileName(fileName, expectedIdentifier, expectedExtensions, expectedStorageType);
+ assertApplicationResolveFromFileName(fileName, expectedIdentifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertDefaultResolveFromFileName(final String fileName, final String expectedIdentifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertNotNull(DEFAULT_MEDIA_RESOLVER);
+ assertResolveFromFileName(DEFAULT_MEDIA_RESOLVER, fileName, expectedIdentifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertApplicationResolveFromFileName(final String fileName, final String expectedIdentifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertNotNull(APPLICATION_MEDIA_RESOLVER);
+ assertResolveFromFileName(APPLICATION_MEDIA_RESOLVER, fileName, expectedIdentifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertResolveFromFileName(final MediaTypeResolver mediaTypeResolver, final String fileName, final String expectedIdentifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ // by String
+ @Nullable MediaType mediaType = mediaTypeResolver.fromFileName(fileName);
+ assertNotNull(mediaType);
+ assertEquals(expectedIdentifier, mediaType.getIdentifier());
+ assertArrayAnyOrderEquals(expectedExtensions, mediaType.getKnownFileExtensions());
+ assertEquals(expectedStorageType, mediaType.getStorageType());
+
+ // by Path
+ mediaType = mediaTypeResolver.fromFileName(Paths.get(fileName));
+ assertNotNull(mediaType);
+ assertEquals(expectedIdentifier, mediaType.getIdentifier());
+ assertArrayAnyOrderEquals(expectedExtensions, mediaType.getKnownFileExtensions());
+ assertEquals(expectedStorageType, mediaType.getStorageType());
+ }
+
+ private void assertAllResolveFromIdentifier(final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertDefaultResolveFromIdentifier(identifier, expectedExtensions, expectedStorageType);
+ assertApplicationResolveFromIdentifier(identifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertDefaultResolveFromIdentifier(final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertNotNull(DEFAULT_MEDIA_RESOLVER);
+ assertResolveFromIdentifier(DEFAULT_MEDIA_RESOLVER, identifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertApplicationResolveFromIdentifier(final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertNotNull(APPLICATION_MEDIA_RESOLVER);
+ assertResolveFromIdentifier(APPLICATION_MEDIA_RESOLVER, identifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertResolveFromIdentifier(final MediaTypeResolver mediaTypeResolver, final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ final @Nullable MediaType mediaType = mediaTypeResolver.fromString(identifier);
+ assertNotNull(mediaType);
+ assertArrayAnyOrderEquals(expectedExtensions, mediaType.getKnownFileExtensions());
+ assertEquals(expectedStorageType, mediaType.getStorageType());
+ }
+
+ private static void assertArrayAnyOrderEquals(final T[] expected, final T[] actual) {
+ Arrays.sort(expected);
+ Arrays.sort(actual);
+ assertArrayEquals(expected, actual);
+ }
+}
diff --git a/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/media-type-mappings.xml b/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/media-type-mappings.xml
new file mode 100644
index 0000000000..6d8e835bbf
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/media-type-mappings.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+ application/xml
+ text/xml
+ application/vnd.oasis.opendocument.
+ application/vnd.openxmlformats-
+ [^+]+\+xml$
+
+
+
\ No newline at end of file
diff --git a/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/mime.types b/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/mime.types
new file mode 100644
index 0000000000..593bca4d7f
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/mime.types
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2014, Evolved Binary Ltd
+#
+# This file was originally ported from FusionDB to Elemental by
+# Evolved Binary, for the benefit of the Elemental Open Source community.
+# Only the ported code as it appears in this file, at the time that
+# it was contributed to Elemental, was re-licensed under The GNU
+# Lesser General Public License v2.1 only for use in Elemental.
+#
+# This license grant applies only to a snapshot of the code as it
+# appeared when ported, it does not offer or infer any rights to either
+# updates of this source code or access to the original source code.
+#
+# The GNU Lesser General Public License v2.1 only license follows.
+#
+# =====================================================================
+#
+# Elemental
+# Copyright (C) 2024, Evolved Binary Ltd
+#
+# admin@evolvedbinary.com
+# https://www.evolvedbinary.com | https://www.elemental.xyz
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; version 2.1.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+application/dita+xml dita ditamap ditaval
+application/prs.existdb.collection-config+xml xconf
+application/prs.expath.package+zip xar
+application/rdf+xml xmp owl rdf
+application/schematron+xml sch
+application/tei+xml odd tei teicorpus
+application/vnd.xmi+xml xmi
+application/xml fo nvdl rng stx xconf xml xsd xsl
+application/xquery xq xql xqm xquery xqws xqy
+application/xquery+xml xqx
+image/svg+xml svg svgz
+# See: https://github.com/w3c/svgwg/issues/701
+# image/x.svg+gzip svgz
+text/markdown md
\ No newline at end of file
diff --git a/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/test/levels/mime.types b/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/test/levels/mime.types
new file mode 100644
index 0000000000..3c4966cf55
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/test/levels/mime.types
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2014, Evolved Binary Ltd
+#
+# This file was originally ported from FusionDB to Elemental by
+# Evolved Binary, for the benefit of the Elemental Open Source community.
+# Only the ported code as it appears in this file, at the time that
+# it was contributed to Elemental, was re-licensed under The GNU
+# Lesser General Public License v2.1 only for use in Elemental.
+#
+# This license grant applies only to a snapshot of the code as it
+# appeared when ported, it does not offer or infer any rights to either
+# updates of this source code or access to the original source code.
+#
+# The GNU Lesser General Public License v2.1 only license follows.
+#
+# =====================================================================
+#
+# Elemental
+# Copyright (C) 2024, Evolved Binary Ltd
+#
+# admin@evolvedbinary.com
+# https://www.evolvedbinary.com | https://www.elemental.xyz
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; version 2.1.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+test/dita+xml dita
+test/prs.existdb.collection-config+xml xconf
+test/extensible-markup-language xadam xml
+test/x.xsl+xml xsl
\ No newline at end of file
diff --git a/elemental-media-type/pom.xml b/elemental-media-type/pom.xml
new file mode 100644
index 0000000000..a7f6f68cdb
--- /dev/null
+++ b/elemental-media-type/pom.xml
@@ -0,0 +1,83 @@
+
+
+
+ 4.0.0
+
+
+ xyz.elemental
+ elemental-parent
+ 7.5.0-SNAPSHOT
+ ../elemental-parent
+
+
+ elemental-media-type
+ pom
+
+ Elemental Internet Media Type Resolver
+ Internet Media Type Resolver API and Implementation for Elemental
+
+
+ scm:git:https://github.com/evolvedbinary/elemental.git
+ scm:git:https://github.com/evolvedbinary/elemental.git
+ scm:git:https://github.com/evolvedbinary/elemental.git
+
+
+
+ elemental-media-type-api
+ elemental-media-type-impl
+
+
+
+
+
+ com.mycila
+ license-maven-plugin
+
+
+
+ ${project.parent.relativePath}/FDB-backport-to-EDB-LGPL-21-ONLY-license.template.txt
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/elemental-parent/FDB-backport-to-EDB-LGPL-21-ONLY-license.template.txt b/elemental-parent/FDB-backport-to-EDB-LGPL-21-ONLY-license.template.txt
new file mode 100644
index 0000000000..b39453e753
--- /dev/null
+++ b/elemental-parent/FDB-backport-to-EDB-LGPL-21-ONLY-license.template.txt
@@ -0,0 +1,34 @@
+Copyright (C) 2014, Evolved Binary Ltd
+
+This file was originally ported from FusionDB to Elemental by
+Evolved Binary, for the benefit of the Elemental Open Source community.
+Only the ported code as it appears in this file, at the time that
+it was contributed to Elemental, was re-licensed under The GNU
+Lesser General Public License v2.1 only for use in Elemental.
+
+This license grant applies only to a snapshot of the code as it
+appeared when ported, it does not offer or infer any rights to either
+updates of this source code or access to the original source code.
+
+The GNU Lesser General Public License v2.1 only license follows.
+
+=====================================================================
+
+Elemental
+Copyright (C) 2024, Evolved Binary Ltd
+
+admin@evolvedbinary.com
+https://www.evolvedbinary.com | https://www.elemental.xyz
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; version 2.1.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
\ No newline at end of file
diff --git a/elemental-parent/pom.xml b/elemental-parent/pom.xml
index 9272aa07c5..e039b32ef1 100644
--- a/elemental-parent/pom.xml
+++ b/elemental-parent/pom.xml
@@ -99,8 +99,10 @@
6.0.0
6.0.0
3.4
+ 2.1.4
4.0.4
4.0.6
+ 2.0.17
1C
@@ -119,12 +121,89 @@
jsr305
3.0.2
+
+
+ io.lacuna
+ bifurcan
+ 0.2.0-rc1
+
+
+
+ net.jcip
+ jcip-annotations
+ 1.0
+
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+
+ jakarta.activation
+ jakarta.activation-api
+ ${jakarta.activation-api.version}
+
+
+
+ org.eclipse.angus
+ angus-activation
+ ${eclipse.angus-activation.version}
+
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ ${jaxb.api.version}
+
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+ ${jaxb.impl.version}
+ runtime
+
+
+
+ com.sun.activation
+ jakarta.activation
+
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.jupiter.version}
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit.jupiter.version}
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit.jupiter.version}
+ test
+
+
+ org.jvnet.jaxb
+ jaxb-maven-plugin
+ 4.0.12
+
org.apache.maven.plugins
maven-compiler-plugin
@@ -238,6 +317,7 @@
SLASHSTAR_STYLE
SLASHSTAR_STYLE
XML_STYLE
+ SCRIPT_STYLE
XML_STYLE
XML_STYLE
XML_STYLE
@@ -474,6 +554,7 @@
${project.parent.relativePath}/elemental-LGPL-21-ONLY-license.template.txt
elemental-LGPL-21-ONLY-license.template.txt
+ FDB-backport-to-EDB-LGPL-21-ONLY-license.template.txt
diff --git a/exist-ant/pom.xml b/exist-ant/pom.xml
index 7663cad2b0..e4355e969d 100644
--- a/exist-ant/pom.xml
+++ b/exist-ant/pom.xml
@@ -80,6 +80,16 @@
exist-start
${project.version}
+
+ xyz.elemental
+ elemental-media-type-api
+ ${project.version}
+
+
+ xyz.elemental
+ elemental-media-type-impl
+ ${project.version}
+
net.sf.xmldb-org
xmldb-api
@@ -174,6 +184,7 @@
pom.xml
src/test/resources-filtered/conf.xml
src/test/resources/log4j2.xml
+ src/main/java/org/exist/ant/XMLDBStoreTask.java
@@ -191,6 +202,7 @@
xquery-license-style.xml
src/test/resources-filtered/conf.xml
src/test/resources/log4j2.xml
+ src/main/java/org/exist/ant/XMLDBStoreTask.java
diff --git a/exist-ant/src/main/java/org/exist/ant/XMLDBStoreTask.java b/exist-ant/src/main/java/org/exist/ant/XMLDBStoreTask.java
index 14e8b0a96e..4f2ba92826 100644
--- a/exist-ant/src/main/java/org/exist/ant/XMLDBStoreTask.java
+++ b/exist-ant/src/main/java/org/exist/ant/XMLDBStoreTask.java
@@ -1,4 +1,28 @@
/*
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ * The original license header is included below.
+ *
+ * =====================================================================
+ *
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
@@ -25,8 +49,7 @@
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
-import org.exist.util.MimeTable;
-import org.exist.util.MimeType;
+import org.exist.mediatype.MediaTypeUtil;
import org.exist.xmldb.EXistResource;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.Constants;
@@ -36,9 +59,14 @@
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.BinaryResource;
import org.xmldb.api.modules.XMLResource;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeResolver;
+import xyz.elemental.mediatype.StorageType;
+import xyz.elemental.mediatype.impl.MediaTypeImpl;
import java.io.File;
import java.util.ArrayList;
+import java.util.List;
/**
@@ -55,17 +83,17 @@
* @author Peter Klotz
*/
public class XMLDBStoreTask extends AbstractXMLDBTask {
- private File mimeTypesFile = null;
+ private File mediaTypesFile = null;
private File srcFile = null;
private String targetFile = null;
- private ArrayList fileSetList = null;
+ private List fileSetList = null;
private boolean createCollection = false;
private boolean createSubcollections = false;
private boolean includeEmptyDirs = true;
private String type = null;
private String defaultMimeType = null;
private String forceMimeType = null;
- private MimeTable mtable = null;
+ private MediaTypeResolver mediaTypeResolver = null;
@Override
public void execute() throws BuildException {
@@ -130,42 +158,61 @@ public void execute() throws BuildException {
if (srcFile != null) {
log("Storing " + srcFile.getName());
- final String baseMimeType;
+ MediaType mediaType = getMediaTypeResolver().fromFileName(srcFile.getName());
+ final String baseMediaType;
+
if (forceMimeType != null) {
- baseMimeType = forceMimeType;
+ baseMediaType = forceMimeType;
+
+ } else if (mediaType != null) {
+ baseMediaType = mediaType.getIdentifier();
+
} else {
- final MimeType fileMime = getMimeTable().getContentTypeFor(srcFile.getName());
- if (fileMime != null) {
- baseMimeType = fileMime.getName();
- } else {
- baseMimeType = defaultMimeType;
+ baseMediaType = defaultMimeType;
+ }
+
+ if (type != null) {
+ if ("xml".equals(type) && (mediaType == null || mediaType.getStorageType() != StorageType.XML)) {
+ if (baseMediaType != null) {
+ mediaType = MediaTypeImpl.builder(baseMediaType, StorageType.XML).build();
+ } else {
+ mediaType = mediaTypeResolver.fromString(MediaType.APPLICATION_XML);
+ }
+
+ } else if ("binary".equals(type) && (mediaType == null || mediaType.getStorageType() != StorageType.BINARY)) {
+ if (baseMediaType != null) {
+ mediaType = MediaTypeImpl.builder(baseMediaType, StorageType.BINARY).build();
+ } else {
+ mediaType = mediaTypeResolver.forUnknown();
+ }
}
}
- final MimeType mime;
- if ("xml".equals(type)) {
- mime = (baseMimeType != null) ? new MimeType(baseMimeType, MimeType.XML) : MimeType.XML_TYPE;
- } else if ("binary".equals(type)) {
- mime = (baseMimeType != null) ? new MimeType(baseMimeType, MimeType.BINARY) : MimeType.BINARY_TYPE;
- } else {
+ // single file
+ if (mediaType == null) {
final String msg = "Cannot guess mime-type kind for " + srcFile.getName() + ". Treating it as a binary.";
log(msg, Project.MSG_ERR);
- mime = (baseMimeType != null) ? new MimeType(baseMimeType, MimeType.BINARY) : MimeType.BINARY_TYPE;
+ if (baseMediaType != null) {
+ mediaType = MediaTypeImpl.builder(baseMediaType, StorageType.BINARY).build();
+ } else {
+ mediaType = mediaTypeResolver.forUnknown();
+ }
}
+ final Class extends Resource> resourceType = mediaType.getStorageType() == StorageType.XML ? XMLResource.class : BinaryResource.class;
+
if (targetFile == null) {
targetFile = srcFile.getName();
}
try {
- final Class extends Resource> resourceType = mime.isXMLType() ? XMLResource.class : BinaryResource.class;
- log("Creating resource " + targetFile + " in collection " + col.getName() + " of type " + resourceType.getName() + " with mime-type: " + mime.getName(), Project.MSG_DEBUG);
+ log("Creating resource " + targetFile + " in collection " + col.getName() + " of type " + resourceType + " with media-type: " + mediaType.getIdentifier(), Project.MSG_DEBUG);
try (Resource res = col.createResource(targetFile, resourceType)) {
if (srcFile.length() == 0) {
// note: solves bug id 2429889 when this task hits empty files
} else {
res.setContent(srcFile);
- ((EXistResource) res).setMimeType(mime.getName());
+ ((EXistResource) res).setMediaType(mediaType.getIdentifier());
col.storeResource(res);
}
@@ -266,40 +313,53 @@ public void execute() throws BuildException {
col = root;
}
- MimeType currentMime = getMimeTable().getContentTypeFor(file.getName());
- final String currentBaseMimeType;
+ MediaType currentMediaType = getMediaTypeResolver().fromFileName(file.getName());
+ final String currentBaseMediaType;
if (forceMimeType != null) {
- currentBaseMimeType = forceMimeType;
+ currentBaseMediaType = forceMimeType;
- } else if (currentMime != null) {
- currentBaseMimeType = currentMime.getName();
+ } else if (currentMediaType != null) {
+ currentBaseMediaType = currentMediaType.getIdentifier();
} else {
- currentBaseMimeType = defaultMimeType;
+ currentBaseMediaType = defaultMimeType;
}
if (type != null) {
- if ("xml".equals(type)) {
- currentMime = (currentBaseMimeType != null) ? (new MimeType(currentBaseMimeType, MimeType.XML)) : MimeType.XML_TYPE;
- } else if ("binary".equals(type)) {
- currentMime = (currentBaseMimeType != null) ? (new MimeType(currentBaseMimeType, MimeType.BINARY)) : MimeType.BINARY_TYPE;
+ if ("xml".equals(type) && (currentMediaType == null || currentMediaType.getStorageType() != StorageType.XML)) {
+ if (currentBaseMediaType != null) {
+ currentMediaType = MediaTypeImpl.builder(currentBaseMediaType, StorageType.XML).build();
+ } else {
+ currentMediaType = mediaTypeResolver.fromString(MediaType.APPLICATION_XML);
+ }
+
+ } else if ("binary".equals(type) && (currentMediaType == null || currentMediaType.getStorageType() != StorageType.BINARY)) {
+ if (currentBaseMediaType != null) {
+ currentMediaType = MediaTypeImpl.builder(currentBaseMediaType, StorageType.BINARY).build();
+ } else {
+ currentMediaType = mediaTypeResolver.forUnknown();
+ }
}
}
- if (currentMime == null) {
+ if (currentMediaType == null) {
final String msg = "Cannot find mime-type kind for " + file.getName() + ". Treating it as a binary.";
log(msg, Project.MSG_ERR);
- currentMime = (currentBaseMimeType != null) ? (new MimeType(currentBaseMimeType, MimeType.BINARY)) : MimeType.BINARY_TYPE;
+ if (currentBaseMediaType != null) {
+ currentMediaType = MediaTypeImpl.builder(currentBaseMediaType, StorageType.BINARY).build();
+ } else {
+ currentMediaType = mediaTypeResolver.forUnknown();
+ }
}
- final Class extends Resource> resourceType = currentMime.isXMLType() ? XMLResource.class : BinaryResource.class;
- log("Creating resource " + file.getName() + " in collection " + col.getName() + " of type " + resourceType.getName() + " with mime-type: " + currentMime.getName(), Project.MSG_DEBUG);
+ final Class extends Resource> resourceType = currentMediaType.getStorageType() == StorageType.XML ? XMLResource.class : BinaryResource.class;
+ log("Creating resource " + file.getName() + " in collection " + col.getName() + " of type " + resourceType + " with media-type: " + currentMediaType.getIdentifier(), Project.MSG_DEBUG);
try (Resource res = col.createResource(file.getName(), resourceType)) {
res.setContent(file);
- ((EXistResource) res).setMimeType(currentMime.getName());
+ ((EXistResource) res).setMediaType(currentMediaType.getIdentifier());
col.storeResource(res);
if (permissions != null) {
@@ -354,8 +414,12 @@ public void setIncludeEmptyDirs(final boolean create) {
this.includeEmptyDirs = create;
}
- public void setMimeTypesFile(final File file) {
- this.mimeTypesFile = file;
+ public void setMimeTypesFile(final File mediaTypesFile) {
+ setMediaTypesFile(mediaTypesFile);
+ }
+
+ public void setMediaTypesFile(final File mediaTypesFile) {
+ this.mediaTypesFile = mediaTypesFile;
}
public void setType(final String type) {
@@ -370,17 +434,19 @@ public void setForceMimeType(final String mimeType) {
this.forceMimeType = mimeType;
}
- private MimeTable getMimeTable() throws BuildException {
- if (mtable == null) {
- if (mimeTypesFile != null && mimeTypesFile.exists()) {
- log("Trying to use MIME Types file " + mimeTypesFile.getAbsolutePath(), Project.MSG_DEBUG);
- mtable = MimeTable.getInstance(mimeTypesFile.toPath());
- } else {
+ private MediaTypeResolver getMediaTypeResolver() throws BuildException {
+ if (mediaTypeResolver == null) {
+ if (mediaTypesFile != null && mediaTypesFile.exists()) {
+ log("Trying to use MIME Types file " + mediaTypesFile.getAbsolutePath(), Project.MSG_DEBUG);
+ mediaTypeResolver = MediaTypeUtil.newMediaTypeResolver(mediaTypesFile.getParentFile().toPath());
+ }
+
+ if (mediaTypeResolver == null) {
log("Using default MIME Types resources", Project.MSG_DEBUG);
- mtable = MimeTable.getInstance();
+ mediaTypeResolver = MediaTypeUtil.newMediaTypeResolver(null);
}
}
- return mtable;
+ return mediaTypeResolver;
}
}
diff --git a/exist-core-jmh/pom.xml b/exist-core-jmh/pom.xml
index e48d45b3d3..6c6b2ee2bd 100644
--- a/exist-core-jmh/pom.xml
+++ b/exist-core-jmh/pom.xml
@@ -141,7 +141,7 @@
- ${project.parent.relativePath}/FDB-backport-LGPL-21-ONLY-license.template.txt
+ ${project.parent.relativePath}/FDB-backport-to-existdb-LGPL-21-ONLY-license.template.txt
src/main/java/org/exist/storage/lock/LockTableBenchmark.java
src/main/java/org/exist/xquery/utils/StringJoinBenchmark.java
diff --git a/exist-core/FDB-backport-BSD-3-license.template.txt b/exist-core/FDB-backport-to-existdb-BSD-3-license.template.txt
similarity index 100%
rename from exist-core/FDB-backport-BSD-3-license.template.txt
rename to exist-core/FDB-backport-to-existdb-BSD-3-license.template.txt
diff --git a/exist-core/pom.xml b/exist-core/pom.xml
index 377bea02d7..8e864fe90c 100644
--- a/exist-core/pom.xml
+++ b/exist-core/pom.xml
@@ -202,6 +202,18 @@
${project.version}
+
+ xyz.elemental
+ elemental-media-type-api
+ ${project.version}
+
+
+
+ xyz.elemental
+ elemental-media-type-impl
+ ${project.version}
+
+
org.exquery
exquery-common
@@ -789,6 +801,7 @@
src/test/resources-filtered/conf.xml
src/test/resources/log4j2.xml
src/test/resources/standalone-webapp/WEB-INF/web.xml
+ src/main/xjb/rest-api.xjb
src/test/xquery/tail-recursion.xml
src/test/xquery/maps/maps.xqm
src/test/xquery/util/util.xml
@@ -802,12 +815,22 @@
src/main/java/org/exist/Namespaces.java
src/main/resources-filtered/org/exist/system.properties
src/test/java/org/exist/TestDataGenerator
+ src/main/java/org/exist/backup/Backup.java
+ src/main/java/org/exist/backup/CreateBackupDialog.java
+ src/test/java/org/exist/backup/DeepEmbeddedBackupRestoreTest.java
src/main/java/org/exist/backup/ExportGUI.java
src/main/java/org/exist/backup/ExportMain.java
src/main/java/org/exist/backup/Main.java
+ src/main/java/org/exist/backup/Restore.java
+ src/test/java/org/exist/backup/RestoreAppsTest.java
src/main/java/org/exist/backup/SystemExport.java
+ src/test/java/org/exist/backup/SystemExportFiltersTest.java
+ src/test/java/org/exist/backup/SystemExportImportTest.java
+ src/test/java/org/exist/backup/XMLDBRestoreTest.java
src/main/java/org/exist/backup/ZipWriter.java
+ src/main/java/org/exist/backup/restore/AbstractRestoreHandler.java
src/main/java/org/exist/backup/restore/AppRestoreUtils.java
+ src/main/java/org/exist/backup/xquery/RetrieveBackup.java
src/main/java/org/exist/client/ClientFrame.java
src/main/java/org/exist/client/CommandlineOptions.java
src/main/java/org/exist/client/Connection.java
@@ -815,6 +838,7 @@
src/main/java/org/exist/client/DocumentView.java
src/main/java/org/exist/client/IndexDialog.java
src/main/java/org/exist/client/InteractiveClient.java
+ src/main/java/org/exist/client/MediaTypeFileFilter.java
src/main/resources/org/exist/client/messages.properties
src/main/resources/org/exist/client/messages_es_ES.properties
src/main/resources/org/exist/client/messages_fr_FR.properties
@@ -836,6 +860,8 @@
src/main/java/org/exist/collections/Collection.java
src/main/java/org/exist/collections/CollectionConfiguration.java
src/main/java/org/exist/collections/CollectionConfigurationManager.java
+ src/test/java/org/exist/collections/CollectionOrderTest.java
+ src/test/java/org/exist/collections/CollectionRemovalTest.java
src/test/java/org/exist/collections/CollectionStoreTest.java
src/main/java/org/exist/collections/LockedCollection.java
src/main/java/org/exist/collections/MutableCollection.java
@@ -844,13 +870,20 @@
src/main/java/org/exist/collections/triggers/CollectionTriggers.java
src/main/java/org/exist/collections/triggers/DocumentTrigger.java
src/main/java/org/exist/collections/triggers/DocumentTriggers.java
+ src/test/java/org/exist/collections/triggers/HistoryTriggerTest.java
src/test/java/org/exist/collections/triggers/MessagesTrigger.java
src/test/java/org/exist/collections/triggers/TriggerConfigTest.java
src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java
src/main/java/org/exist/collections/triggers/XQueryTrigger.java
+ src/test/java/org/exist/collections/triggers/XQueryTrigger2Test.java
+ src/test/java/org/exist/collections/triggers/XQueryTriggerChainTest.java
+ src/test/java/org/exist/collections/triggers/XQueryTriggerSetGidTest.java
+ src/test/java/org/exist/collections/triggers/XQueryTriggerSetUidTest.java
+ src/test/java/org/exist/collections/triggers/XQueryTriggerTest.java
src/main/java/org/exist/config/Configuration.java
src/main/java/org/exist/config/ConfigurationImpl.java
src/main/java/org/exist/config/Configurator.java
+ src/test/java/org/exist/config/TwoDatabasesTest.java
src/test/java/org/exist/deadlocks/GetReleaseBrokerDeadlocksTest.java
src/main/java/org/exist/dom/NodeListImpl.java
src/main/java/org/exist/dom/QName.java
@@ -871,9 +904,13 @@
src/main/java/org/exist/dom/persistent/AbstractArrayNodeSet.java
src/main/java/org/exist/dom/persistent/AbstractCharacterData.java
src/main/java/org/exist/dom/persistent/AttrImpl.java
+ src/test/java/org/exist/dom/persistent/BasicNodeSetTest.java
src/main/java/org/exist/dom/persistent/BinaryDocument.java
+ src/test/java/org/exist/dom/persistent/CDataIntergationTest.java
src/main/java/org/exist/dom/persistent/CommentImpl.java
+ src/test/java/org/exist/dom/persistent/CommentTest.java
src/test/java/org/exist/dom/persistent/DefaultDocumentSetTest.java
+ src/test/java/org/exist/dom/persistent/DocTypeTest.java
src/main/java/org/exist/dom/persistent/DocumentImpl.java
src/main/java/org/exist/dom/persistent/DocumentMetadata.java
src/main/java/org/exist/dom/persistent/DocumentSet.java
@@ -895,19 +932,25 @@
src/main/java/org/exist/dom/persistent/XMLUtil.java
src/test/java/org/exist/http/AbstractHttpTest.java
src/main/java/org/exist/http/AuditTrailSessionListener.java
+ src/test/java/org/exist/http/AuditTrailSessionListenerTest.java
src/main/java/org/exist/http/Descriptor.java
+ src/main/java/org/exist/http/Response.java
src/main/java/org/exist/http/RESTServer.java
src/test/java/org/exist/http/RESTServiceTest.java
src/main/java/org/exist/http/servlets/AbstractExistHttpServlet.java
src/main/java/org/exist/http/servlets/EXistServlet.java
+ src/main/java/org/exist/http/servlets/HttpServletRequestWrapper.java
src/main/java/org/exist/http/servlets/RedirectorServlet.java
src/main/java/org/exist/http/servlets/XQueryServlet.java
src/main/java/org/exist/http/servlets/XSLTServlet.java
+ src/test/java/org/exist/http/urlrewrite/ControllerTest.java
src/main/java/org/exist/http/urlrewrite/ModuleCall.java
src/main/java/org/exist/http/urlrewrite/PathForward.java
src/main/java/org/exist/http/urlrewrite/Redirect.java
src/main/java/org/exist/http/urlrewrite/RewriteConfig.java
+ src/test/java/org/exist/http/urlrewrite/URLRewritingTest.java
src/main/java/org/exist/http/urlrewrite/XQueryURLRewrite.java
+ src/test/java/org/exist/http/urlrewrite/XQueryURLRewriteTest.java
src/main/java/org/exist/indexing/Index.java
src/main/java/org/exist/indexing/IndexController.java
src/main/java/org/exist/indexing/IndexManager.java
@@ -936,10 +979,20 @@
src/main/java/org/exist/management/impl/SanityReport.java
src/main/java/org/exist/numbering/DLN.java
src/main/java/org/exist/numbering/DLNFactory.java
+ src/test/java/org/exist/numbering/DLNStorageTest.java
src/main/java/org/exist/numbering/NodeId.java
src/main/java/org/exist/numbering/NodeIdFactory.java
+ src/main/java/org/exist/protocolhandler/eXistURLStreamHandlerFactory.java
+ src/main/java/org/exist/protocolhandler/URLStreamHandlerStartupTrigger.java
+ src/main/java/org/exist/protocolhandler/embedded/EmbeddedOutputStream.java
+ src/main/java/org/exist/protocolhandler/embedded/InMemoryOutputStream.java
+ src/main/java/org/exist/protocolhandler/protocols/xmldb/EmbeddedURLConnection.java
+ src/main/java/org/exist/protocolhandler/protocols/xmldb/Handler.java
+ src/main/java/org/exist/protocolhandler/protocols/xmldb/InMemoryURLConnection.java
src/main/java/org/exist/protocolhandler/xmldb/XmldbURL.java
+ src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcOutputStream.java
src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcUpload.java
+ src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcUploadRunnable.java
src/main/java/org/exist/repo/AutoDeploymentTrigger.java
src/main/java/org/exist/repo/ClasspathHelper.java
src/main/java/org/exist/repo/Deployment.java
@@ -950,6 +1003,7 @@
src/test/java/org/exist/security/FnDocSecurityTest.java
src/main/java/org/exist/security/Permission.java
src/main/java/org/exist/security/PermissionRequired.java
+ src/test/java/org/exist/security/RestApiSecurityTest.java
src/main/java/org/exist/security/SecurityManager.java
src/main/java/org/exist/security/SimpleACLPermissionInternal.java
src/test/java/org/exist/security/SimpleACLPermissionTest.java
@@ -960,27 +1014,51 @@
src/main/java/org/exist/security/internal/aider/UnixStylePermissionAider.java
src/main/java/org/exist/source/Source.java
src/main/java/org/exist/source/SourceFactory.java
+ src/main/java/org/exist/source/URLSource.java
+ src/test/java/org/exist/stax/EmbeddedXMLStreamReaderTest.java
+ src/test/java/org/exist/storage/AbstractUpdateTest.java
src/test/java/org/exist/storage/BFileRecoverTest.java
+ src/test/java/org/exist/storage/BinaryDocumentTest.java
src/main/java/org/exist/storage/BrokerFactory.java
src/main/java/org/exist/storage/BrokerPool.java
src/test/java/org/exist/storage/BrokerPoolsTest.java
src/test/java/org/exist/storage/BrokerPoolTest.java
src/test/java/org/exist/storage/CollectionTest.java
+ src/test/java/org/exist/storage/ConcurrentBrokerPoolTest.java
+ src/test/java/org/exist/storage/ConcurrentStoreTest.java
+ src/test/java/org/exist/storage/CopyCollectionRecoveryTest.java
+ src/test/java/org/exist/storage/CopyResourceRecoveryTest.java
src/test/java/org/exist/storage/CopyResourceTest.java
src/main/java/org/exist/storage/DBBroker.java
+ src/test/java/org/exist/storage/DirtyShutdownTest.java
src/test/java/org/exist/storage/DOMFileRecoverTest.java
src/main/java/org/exist/storage/Indexable.java
src/main/java/org/exist/storage/IndexSpec.java
+ src/test/java/org/exist/storage/LargeValuesTest.java
+ src/test/java/org/exist/storage/ModificationTimeTest.java
+ src/test/java/org/exist/storage/MoveCollectionRecoveryTest.java
+ src/test/java/org/exist/storage/MoveOverwriteCollectionTest.java
+ src/test/java/org/exist/storage/MoveOverwriteResourceTest.java
+ src/test/java/org/exist/storage/MoveResourceRecoveryTest.java
src/main/java/org/exist/storage/NativeBroker.java
src/main/java/org/exist/storage/NativeValueIndex.java
src/main/java/org/exist/storage/NodePath.java
src/test/java/org/exist/storage/NodePathTest.java
src/main/java/org/exist/storage/ProcessMonitor.java
+ src/test/java/org/exist/storage/RangeIndexUpdateTest.java
src/test/java/org/exist/storage/RecoverBinary2Test.java
src/test/java/org/exist/storage/Recovery2Test.java
src/test/java/org/exist/storage/RecoveryTest.java
+ src/test/java/org/exist/storage/ReindexRecoveryTest.java
+ src/test/java/org/exist/storage/ReindexTest.java
src/test/java/org/exist/storage/RemoveCollectionTest.java
+ src/test/java/org/exist/storage/RemoveRootCollectionTest.java
+ src/test/java/org/exist/storage/ResourceTest.java
+ src/test/java/org/exist/storage/ShutdownTest.java
src/main/java/org/exist/storage/StorageAddress.java
+ src/test/java/org/exist/storage/StoreBinaryTest.java
+ src/test/java/org/exist/storage/StoreResourceTest.java
+ src/test/java/org/exist/storage/UpdateRecoverTest.java
src/test/java/org/exist/storage/XIncludeSerializerTest.java
src/test/java/org/exist/storage/btree/BTreeTest.java
src/main/java/org/exist/storage/btree/TreeMetrics.java
@@ -993,6 +1071,7 @@
src/test/java/org/exist/storage/io/VariableByteStreamTest.java
src/test/java/org/exist/storage/lock/DeadlockTest.java
src/main/java/org/exist/storage/lock/FileLock.java
+ src/test/java/org/exist/storage/lock/GetXMLResourceNoLockTest.java
src/test/java/org/exist/storage/lock/ProtectedModeTest.java
src/main/java/org/exist/storage/recovery/RecoveryManager.java
src/main/java/org/exist/storage/serializers/EXistOutputKeys.java
@@ -1019,7 +1098,14 @@
src/main/java/org/exist/util/Configuration.java
src/test/java/org/exist/util/DOMSerializerTest.java
src/test/java/org/exist/util/LeasableTest.java
+ src/test/java/org/exist/util/MediaTypeResolverTest.java
+ src/main/java/org/exist/util/MimeTable.java
+ src/main/java/org/exist/util/MimeType.java
src/main/java/org/exist/util/ParametersExtractor.java
+ src/main/java/org/exist/util/XMLFilenameFilter.java
+ src/test/java/org/exist/util/XMLReaderExpansionTest.java
+ src/test/java/org/exist/util/XMLReaderSecurityTest.java
+ src/main/java/org/exist/util/XQueryFilenameFilter.java
src/main/java/org/exist/util/crypto/digest/DigestType.java
src/main/java/org/exist/util/io/ByteArrayContent.java
src/test/java/org/exist/util/io/ByteArrayContentTest.java
@@ -1050,6 +1136,7 @@
src/test/java/org/exist/util/sorters/SortTestNodeId.java
src/test/resources/org/exist/validation/catalog.xml
src/test/java/org/exist/validation/CollectionConfigurationValidationModeTest.java
+ src/test/java/org/exist/validation/DtdEntityTest.java
src/main/java/org/exist/validation/XmlLibraryChecker.java
src/main/java/org/exist/validation/internal/DatabaseResources.java
src/main/resources/org/exist/validation/internal/query/find_catalogs_with_dtd.xq
@@ -1057,6 +1144,8 @@
src/main/java/org/exist/validation/resolver/SearchResourceResolver.java
src/test/java/org/exist/w3c/tests/TestCase.java
src/main/java/org/exist/webstart/JnlpJarFiles.java
+ src/main/java/org/exist/webstart/JnlpWriter.java
+ src/main/java/org/exist/xmldb/AbstractEXistResource.java
src/main/java/org/exist/xmldb/AbstractRemoteResource.java
src/test/java/org/exist/xmldb/ContentAsDOMTest.java
src/test/java/org/exist/xmldb/CreateCollectionsTest.java
@@ -1064,11 +1153,16 @@
src/test/java/org/exist/xmldb/EXistXMLSerializeTest.java
src/test/java/org/exist/xmldb/IndexingTest.java
src/main/java/org/exist/xmldb/LocalBinaryResource.java
+ src/main/java/org/exist/xmldb/LocalCollection.java
src/main/java/org/exist/xmldb/LocalResourceSet.java
+ src/main/java/org/exist/xmldb/LocalRestoreService.java
src/main/java/org/exist/xmldb/LocalXMLResource.java
src/main/java/org/exist/xmldb/LocalXPathQueryService.java
src/main/java/org/exist/xmldb/RemoteBinaryResource.java
+ src/main/java/org/exist/xmldb/RemoteCollection.java
+ src/test/java/org/exist/xmldb/RemoteCollectionTest.java
src/test/java/org/exist/xmldb/RemoteDOMTest.java
+ src/test/java/org/exist/xmldb/RemoteQueryTest.java
src/main/java/org/exist/xmldb/RemoteResourceSet.java
src/main/java/org/exist/xmldb/RemoteRestoreService.java
src/main/java/org/exist/xmldb/RemoteXMLResource.java
@@ -1095,6 +1189,7 @@
src/test/java/org/exist/xmlrpc/QuerySessionTest.java
src/main/java/org/exist/xmlrpc/RpcAPI.java
src/main/java/org/exist/xmlrpc/RpcConnection.java
+ src/test/java/org/exist/xmlrpc/XmlRpcTest.java
src/main/java/org/exist/xqj/Marshaller.java
src/test/java/org/exist/xqj/MarshallerTest.java
src/main/java/org/exist/xquery/AbstractInternalModule.java
@@ -1106,12 +1201,14 @@
src/main/java/org/exist/xquery/DynamicCardinalityCheck.java
src/main/java/org/exist/xquery/DynamicTypeCheck.java
src/main/java/org/exist/xquery/DynamicVariable.java
+ src/test/java/org/exist/xquery/EmbeddedBinariesTest.java
src/test/java/org/exist/xquery/EmbeddedBinariesTest.java.java
src/main/java/org/exist/xquery/ErrorCodes.java
src/main/java/org/exist/xquery/ExternalModuleImpl.java
src/test/java/org/exist/xquery/ForwardReferenceTest.java
src/main/java/org/exist/xquery/Function.java
src/main/java/org/exist/xquery/FunctionFactory.java
+ src/test/java/org/exist/xquery/LexerTest.java
src/main/java/org/exist/xquery/LocationStep.java
src/main/java/org/exist/xquery/Module.java
src/main/java/org/exist/xquery/NamedFunctionReference.java
@@ -1122,18 +1219,21 @@
src/main/java/org/exist/xquery/PerformanceStatsImpl.java
src/test/java/org/exist/xquery/RestBinariesTest.java
src/test/java/org/exist/xquery/StoredModuleTest.java
+ src/test/java/org/exist/xquery/TransformTest.java
src/main/java/org/exist/xquery/TryCatchExpression.java
src/main/java/org/exist/xquery/UserDefinedFunction.java
src/main/java/org/exist/xquery/Variable.java
src/main/java/org/exist/xquery/VariableDeclaration.java
src/main/java/org/exist/xquery/VariableImpl.java
src/main/java/org/exist/xquery/VariableReference.java
+ src/test/java/org/exist/xquery/VariablesTest.java
src/test/java/org/exist/xquery/WindowClauseTest.java
src/test/java/org/exist/xquery/XmldbBinariesTest.java
src/test/java/org/exist/xquery/XPathOpOrSpecialCaseTest.java
src/test/java/org/exist/xquery/XPathQueryTest.java
src/main/java/org/exist/xquery/XPathUtil.java
src/main/java/org/exist/xquery/XQueryContext.java
+ src/test/java/org/exist/xquery/XQueryDeclareContextItemTest.java
src/test/java/org/exist/xquery/XQueryFunctionsTest.java
src/main/java/org/exist/xquery/XQueryProcessingInstruction.java
src/test/java/org/exist/xquery/XQueryProcessingInstructionTest.java
@@ -1247,9 +1347,16 @@
src/main/java/org/exist/xquery/functions/fn/transform/Options.java
src/main/java/org/exist/xquery/functions/fn/transform/Transform.java
src/main/java/org/exist/xquery/functions/fn/transform/TreeUtils.java
+ src/test/java/org/exist/xquery/functions/inspect/InspectModuleTest.java
src/main/java/org/exist/xquery/functions/integer/WordPicture.java
src/main/java/org/exist/xquery/functions/map/MapExpr.java
+ src/main/java/org/exist/xquery/functions/request/GetData.java
+ src/test/java/org/exist/xquery/functions/request/GetData2Test.java
+ src/test/java/org/exist/xquery/functions/request/GetDataTest.java
src/test/java/org/exist/xquery/functions/request/GetHeaderTest.java
+ src/test/java/org/exist/xquery/functions/request/GetParameterTest.java
+ src/test/java/org/exist/xquery/functions/request/PatchTest.java
+ src/main/java/org/exist/xquery/functions/response/Stream.java
src/test/java/org/exist/xquery/functions/securitymanager/GetPermissionsTest.java
src/test/java/org/exist/xquery/functions/securitymanager/GroupManagementFunctionRemoveGroupTest.java
src/test/java/org/exist/xquery/functions/securitymanager/GroupMembershipFunctionRemoveGroupMemberTest.java
@@ -1258,6 +1365,7 @@
src/test/java/org/exist/xquery/functions/securitymanager/PermissionsFunctionChownTest.java
src/test/java/org/exist/xquery/functions/system/GetRunningXQueriesTest.java
src/main/java/org/exist/xquery/functions/system/GetUptime.java
+ src/main/java/org/exist/xquery/functions/system/Restore.java
src/main/java/org/exist/xquery/functions/system/Shutdown.java
src/main/java/org/exist/xquery/functions/system/SystemModule.java
src/main/java/org/exist/xquery/functions/system/TriggerSystemTask.java
@@ -1267,6 +1375,8 @@
src/test/java/org/exist/xquery/functions/transform/TransformTest.java
src/main/java/org/exist/xquery/functions/util/BuiltinFunctions.java
src/main/java/org/exist/xquery/functions/util/DescribeFunction.java
+ src/test/java/org/exist/xquery/functions/util/EvalTest.java
+ src/test/java/org/exist/xquery/functions/util/ExpandTest.java
src/main/java/org/exist/xquery/functions/util/FunctionFunction.java
src/main/java/org/exist/xquery/functions/util/LogFunction.java
src/main/java/org/exist/xquery/functions/util/ModuleInfo.java
@@ -1280,7 +1390,10 @@
src/test/java/org/exist/xquery/functions/validate/JingXsdTest.java
src/main/java/org/exist/xquery/functions/validation/Jaxp.java
src/test/java/org/exist/xquery/functions/xmldb/DbStore2Test.java
+ src/main/java/org/exist/xquery/functions/xmldb/XMLDBGetMimeType.java
+ src/main/java/org/exist/xquery/functions/xmldb/XMLDBLoadFromPattern.java
src/main/java/org/exist/xquery/functions/xmldb/XMLDBModule.java
+ src/main/java/org/exist/xquery/functions/xmldb/XMLDBSetMimeType.java
src/main/java/org/exist/xquery/functions/xmldb/XMLDBStore.java
src/main/java/org/exist/xquery/functions/xmldb/XMLDBXUpdate.java
src/test/java/org/exist/xquery/functions/xquery3/TryCatchTest.java
@@ -1288,6 +1401,7 @@
src/test/java/org/exist/xquery/update/AbstractUpdateTest.java
src/test/java/org/exist/xquery/update/IndexIntegrationTest.java
src/test/java/org/exist/xquery/update/UpdateInsertTest.java
+ src/test/java/org/exist/xquery/update/UpdateInsertTriggersDefragTest.java
src/test/java/org/exist/xquery/update/UpdateReplaceTest.java
src/test/java/org/exist/xquery/update/UpdateValueTest.java
src/main/java/org/exist/xquery/util/ExpressionDumper.java
@@ -1352,7 +1466,7 @@
ARC-BSD-3-license.template.txt
BX-BSD-3-license.template.txt
DBXML-10-license.template.txt
- FDB-backport-BSD-3-license.template.txt
+ FDB-backport-to-existdb-BSD-3-license.template.txt
src/test/resources/uk-towns.txt
src/test/resources/**/*.bin
src/test/resources/**/*.xar
@@ -1366,6 +1480,7 @@
src/test/resources-filtered/conf.xml
src/test/resources/log4j2.xml
src/test/resources/standalone-webapp/WEB-INF/web.xml
+ src/main/xjb/rest-api.xjb
src/test/xquery/binary-value.xqm
src/test/xquery/instance-of.xqm
src/test/xquery/operator-mapping.xqm
@@ -1391,12 +1506,22 @@
src/main/java/org/exist/Namespaces.java
src/main/resources-filtered/org/exist/system.properties
src/test/java/org/exist/TestDataGenerator
+ src/main/java/org/exist/backup/Backup.java
+ src/main/java/org/exist/backup/CreateBackupDialog.java
+ src/test/java/org/exist/backup/DeepEmbeddedBackupRestoreTest.java
src/main/java/org/exist/backup/ExportGUI.java
src/main/java/org/exist/backup/ExportMain.java
src/main/java/org/exist/backup/Main.java
+ src/main/java/org/exist/backup/Restore.java
+ src/test/java/org/exist/backup/RestoreAppsTest.java
src/main/java/org/exist/backup/SystemExport.java
+ src/test/java/org/exist/backup/SystemExportFiltersTest.java
+ src/test/java/org/exist/backup/SystemExportImportTest.java
+ src/test/java/org/exist/backup/XMLDBRestoreTest.java
src/main/java/org/exist/backup/ZipWriter.java
+ src/main/java/org/exist/backup/restore/AbstractRestoreHandler.java
src/main/java/org/exist/backup/restore/AppRestoreUtils.java
+ src/main/java/org/exist/backup/xquery/RetrieveBackup.java
src/main/java/org/exist/client/ClientFrame.java
src/main/java/org/exist/client/CommandlineOptions.java
src/main/java/org/exist/client/Connection.java
@@ -1404,6 +1529,7 @@
src/main/java/org/exist/client/DocumentView.java
src/main/java/org/exist/client/IndexDialog.java
src/main/java/org/exist/client/InteractiveClient.java
+ src/main/java/org/exist/client/MediaTypeFileFilter.java
src/main/resources/org/exist/client/messages.properties
src/main/resources/org/exist/client/messages_es_ES.properties
src/main/resources/org/exist/client/messages_fr_FR.properties
@@ -1425,6 +1551,8 @@
src/main/java/org/exist/collections/Collection.java
src/main/java/org/exist/collections/CollectionConfiguration.java
src/main/java/org/exist/collections/CollectionConfigurationManager.java
+ src/test/java/org/exist/collections/CollectionOrderTest.java
+ src/test/java/org/exist/collections/CollectionRemovalTest.java
src/test/java/org/exist/collections/CollectionStoreTest.java
src/main/java/org/exist/collections/LockedCollection.java
src/main/java/org/exist/collections/MutableCollection.java
@@ -1433,13 +1561,20 @@
src/main/java/org/exist/collections/triggers/CollectionTriggers.java
src/main/java/org/exist/collections/triggers/DocumentTrigger.java
src/main/java/org/exist/collections/triggers/DocumentTriggers.java
+ src/test/java/org/exist/collections/triggers/HistoryTriggerTest.java
src/test/java/org/exist/collections/triggers/MessagesTrigger.java
src/test/java/org/exist/collections/triggers/TriggerConfigTest.java
src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java
src/main/java/org/exist/collections/triggers/XQueryTrigger.java
+ src/test/java/org/exist/collections/triggers/XQueryTrigger2Test.java
+ src/test/java/org/exist/collections/triggers/XQueryTriggerChainTest.java
+ src/test/java/org/exist/collections/triggers/XQueryTriggerSetGidTest.java
+ src/test/java/org/exist/collections/triggers/XQueryTriggerSetUidTest.java
+ src/test/java/org/exist/collections/triggers/XQueryTriggerTest.java
src/main/java/org/exist/config/Configuration.java
src/main/java/org/exist/config/ConfigurationImpl.java
src/main/java/org/exist/config/Configurator.java
+ src/test/java/org/exist/config/TwoDatabasesTest.java
src/test/java/org/exist/deadlocks/GetReleaseBrokerDeadlocksTest.java
src/main/java/org/exist/dom/NodeListImpl.java
src/main/java/org/exist/dom/QName.java
@@ -1468,9 +1603,13 @@
src/main/java/org/exist/dom/persistent/AbstractArrayNodeSet.java
src/main/java/org/exist/dom/persistent/AbstractCharacterData.java
src/main/java/org/exist/dom/persistent/AttrImpl.java
+ src/test/java/org/exist/dom/persistent/BasicNodeSetTest.java
src/main/java/org/exist/dom/persistent/BinaryDocument.java
+ src/test/java/org/exist/dom/persistent/CDataIntergationTest.java
src/main/java/org/exist/dom/persistent/CommentImpl.java
+ src/test/java/org/exist/dom/persistent/CommentTest.java
src/test/java/org/exist/dom/persistent/DefaultDocumentSetTest.java
+ src/test/java/org/exist/dom/persistent/DocTypeTest.java
src/main/java/org/exist/dom/persistent/DocumentImpl.java
src/main/java/org/exist/dom/persistent/DocumentMetadata.java
src/main/java/org/exist/dom/persistent/DocumentSet.java
@@ -1493,21 +1632,27 @@
src/main/java/org/exist/dom/persistent/XMLUtil.java
src/test/java/org/exist/http/AbstractHttpTest.java
src/main/java/org/exist/http/AuditTrailSessionListener.java
+ src/test/java/org/exist/http/AuditTrailSessionListenerTest.java
src/main/java/org/exist/http/Descriptor.java
+ src/main/java/org/exist/http/Response.java
src/test/java/org/exist/http/RESTExternalVariableTest.java
src/main/java/org/exist/http/RESTServer.java
src/test/java/org/exist/http/RESTServiceTest.java
src/main/java/org/exist/http/servlets/AbstractExistHttpServlet.java
src/main/java/org/exist/http/servlets/EXistServlet.java
+ src/main/java/org/exist/http/servlets/HttpServletRequestWrapper.java
src/main/java/org/exist/http/servlets/RedirectorServlet.java
src/main/java/org/exist/http/servlets/XQueryServlet.java
src/main/java/org/exist/http/servlets/XSLTServlet.java
+ src/test/java/org/exist/http/urlrewrite/ControllerTest.java
src/main/java/org/exist/http/urlrewrite/ModuleCall.java
src/main/java/org/exist/http/urlrewrite/PathForward.java
src/main/java/org/exist/http/urlrewrite/Redirect.java
src/test/java/org/exist/http/urlrewrite/RedirectTest.java
src/main/java/org/exist/http/urlrewrite/RewriteConfig.java
+ src/test/java/org/exist/http/urlrewrite/URLRewritingTest.java
src/main/java/org/exist/http/urlrewrite/XQueryURLRewrite.java
+ src/test/java/org/exist/http/urlrewrite/XQueryURLRewriteTest.java
src/main/java/org/exist/indexing/Index.java
src/main/java/org/exist/indexing/IndexController.java
src/main/java/org/exist/indexing/IndexManager.java
@@ -1534,12 +1679,24 @@
src/main/java/org/exist/management/impl/ExistMBean.java
src/main/java/org/exist/management/impl/JMXAgent.java
src/main/java/org/exist/management/impl/SanityReport.java
+ src/main/java/org/exist/mediatype/MediaTypeService.java
+ src/main/java/org/exist/mediatype/MediaTypeUtil.java
src/main/java/org/exist/numbering/DLN.java
src/main/java/org/exist/numbering/DLNFactory.java
+ src/test/java/org/exist/numbering/DLNStorageTest.java
src/main/java/org/exist/numbering/NodeId.java
src/main/java/org/exist/numbering/NodeIdFactory.java
+ src/main/java/org/exist/protocolhandler/eXistURLStreamHandlerFactory.java
+ src/main/java/org/exist/protocolhandler/URLStreamHandlerStartupTrigger.java
+ src/main/java/org/exist/protocolhandler/embedded/EmbeddedOutputStream.java
+ src/main/java/org/exist/protocolhandler/embedded/InMemoryOutputStream.java
+ src/main/java/org/exist/protocolhandler/protocols/xmldb/EmbeddedURLConnection.java
+ src/main/java/org/exist/protocolhandler/protocols/xmldb/Handler.java
+ src/main/java/org/exist/protocolhandler/protocols/xmldb/InMemoryURLConnection.java
src/main/java/org/exist/protocolhandler/xmldb/XmldbURL.java
+ src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcOutputStream.java
src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcUpload.java
+ src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcUploadRunnable.java
src/main/java/org/exist/repo/AutoDeploymentTrigger.java
src/main/java/org/exist/repo/ClasspathHelper.java
src/main/java/org/exist/repo/Deployment.java
@@ -1553,6 +1710,7 @@
src/main/java/org/exist/security/Permission.java
src/main/java/org/exist/security/PermissionRequired.java
src/main/java/org/exist/security/PermissionRequiredCheck.java
+ src/test/java/org/exist/security/RestApiSecurityTest.java
src/main/java/org/exist/security/SecurityManager.java
src/main/java/org/exist/security/SimpleACLPermissionInternal.java
src/test/java/org/exist/security/SimpleACLPermissionTest.java
@@ -1563,8 +1721,12 @@
src/main/java/org/exist/security/internal/aider/UnixStylePermissionAider.java
src/main/java/org/exist/source/Source.java
src/main/java/org/exist/source/SourceFactory.java
+ src/main/java/org/exist/source/URLSource.java
+ src/test/java/org/exist/stax/EmbeddedXMLStreamReaderTest.java
src/test/java/org/exist/storage/AbstractRecoverTest.java
+ src/test/java/org/exist/storage/AbstractUpdateTest.java
src/test/java/org/exist/storage/BFileRecoverTest.java
+ src/test/java/org/exist/storage/BinaryDocumentTest.java
src/main/java/org/exist/storage/BrokerFactory.java
src/main/java/org/exist/storage/BrokerPool.java
src/main/java/org/exist/storage/BrokerPoolService.java
@@ -1575,25 +1737,45 @@
src/test/java/org/exist/storage/BrokerPoolsTest.java
src/test/java/org/exist/storage/BrokerPoolTest.java
src/test/java/org/exist/storage/CollectionTest.java
+ src/test/java/org/exist/storage/ConcurrentBrokerPoolTest.java
+ src/test/java/org/exist/storage/ConcurrentStoreTest.java
+ src/test/java/org/exist/storage/CopyCollectionRecoveryTest.java
+ src/test/java/org/exist/storage/CopyResourceRecoveryTest.java
src/test/java/org/exist/storage/CopyResourceTest.java
src/main/java/org/exist/storage/DBBroker.java
+ src/test/java/org/exist/storage/DirtyShutdownTest.java
src/test/java/org/exist/storage/DOMFileRecoverTest.java
src/main/java/org/exist/storage/FluentBrokerAPI.java
src/main/java/org/exist/storage/Indexable.java
src/main/java/org/exist/storage/IndexSpec.java
+ src/test/java/org/exist/storage/LargeValuesTest.java
+ src/test/java/org/exist/storage/ModificationTimeTest.java
+ src/test/java/org/exist/storage/MoveCollectionRecoveryTest.java
src/test/java/org/exist/storage/MoveCollectionTest.java
+ src/test/java/org/exist/storage/MoveOverwriteCollectionTest.java
+ src/test/java/org/exist/storage/MoveOverwriteResourceTest.java
+ src/test/java/org/exist/storage/MoveResourceRecoveryTest.java
src/main/java/org/exist/storage/NativeBroker.java
src/main/java/org/exist/storage/NativeValueIndex.java
src/main/java/org/exist/storage/NodePath.java
src/test/java/org/exist/storage/NodePathTest.java
src/main/java/org/exist/storage/ProcessMonitor.java
+ src/test/java/org/exist/storage/RangeIndexUpdateTest.java
src/test/java/org/exist/storage/RecoverBinary2Test.java
src/test/java/org/exist/storage/RecoverBinaryTest.java
src/test/java/org/exist/storage/RecoverXmlTest.java
src/test/java/org/exist/storage/Recovery2Test.java
src/test/java/org/exist/storage/RecoveryTest.java
+ src/test/java/org/exist/storage/ReindexRecoveryTest.java
+ src/test/java/org/exist/storage/ReindexTest.java
src/test/java/org/exist/storage/RemoveCollectionTest.java
+ src/test/java/org/exist/storage/RemoveRootCollectionTest.java
+ src/test/java/org/exist/storage/ResourceTest.java
+ src/test/java/org/exist/storage/ShutdownTest.java
src/main/java/org/exist/storage/StorageAddress.java
+ src/test/java/org/exist/storage/StoreBinaryTest.java
+ src/test/java/org/exist/storage/StoreResourceTest.java
+ src/test/java/org/exist/storage/UpdateRecoverTest.java
src/test/java/org/exist/storage/XIncludeSerializerTest.java
src/main/java/org/exist/storage/XQueryPool.java
src/main/java/org/exist/storage/blob/**
@@ -1630,6 +1812,7 @@
src/main/java/org/exist/storage/lock/EnsureUnlocked.java
src/main/java/org/exist/storage/lock/FileLock.java
src/main/java/org/exist/storage/lock/FileLockService.java
+ src/test/java/org/exist/storage/lock/GetXMLResourceNoLockTest.java
src/main/java/org/exist/storage/lock/LockedPath.java
src/main/java/org/exist/storage/lock/LockEventJsonListener.java
src/main/java/org/exist/storage/lock/LockEventLogListener.java
@@ -1685,10 +1868,17 @@
src/main/java/org/exist/util/JREUtil.java
src/test/java/org/exist/util/LeasableTest.java
src/main/java/org/exist/util/MapUtil.java
+ src/test/java/org/exist/util/MediaTypeResolverTest.java
+ src/main/java/org/exist/util/MimeTable.java
+ src/main/java/org/exist/util/MimeType.java
src/main/java/org/exist/util/OSUtil.java
src/main/java/org/exist/util/ParametersExtractor.java
src/main/java/org/exist/util/StringUtil.java
src/main/java/org/exist/util/UTF8.java
+ src/main/java/org/exist/util/XMLFilenameFilter.java
+ src/test/java/org/exist/util/XMLReaderExpansionTest.java
+ src/test/java/org/exist/util/XMLReaderSecurityTest.java
+ src/main/java/org/exist/util/XQueryFilenameFilter.java
src/main/java/org/exist/util/crypto/digest/DigestType.java
src/main/java/org/exist/util/io/AbstractContentFile.java
src/main/java/org/exist/util/io/ByteArrayContent.java
@@ -1721,6 +1911,7 @@
src/test/java/org/exist/util/sorters/SortTestNodeId.java
src/test/resources/org/exist/validation/catalog.xml
src/test/java/org/exist/validation/CollectionConfigurationValidationModeTest.java
+ src/test/java/org/exist/validation/DtdEntityTest.java
src/main/java/org/exist/validation/XmlLibraryChecker.java
src/main/java/org/exist/validation/internal/DatabaseResources.java
src/main/resources/org/exist/validation/internal/query/find_catalogs_with_dtd.xq
@@ -1728,6 +1919,8 @@
src/main/java/org/exist/validation/resolver/SearchResourceResolver.java
src/test/java/org/exist/w3c/tests/TestCase.java
src/main/java/org/exist/webstart/JnlpJarFiles.java
+ src/main/java/org/exist/webstart/JnlpWriter.java
+ src/main/java/org/exist/xmldb/AbstractEXistResource.java
src/main/java/org/exist/xmldb/AbstractRemoteResource.java
src/test/java/org/exist/xmldb/ContentAsDOMTest.java
src/test/java/org/exist/xmldb/CreateCollectionsTest.java
@@ -1735,11 +1928,16 @@
src/test/java/org/exist/xmldb/EXistXMLSerializeTest.java
src/test/java/org/exist/xmldb/IndexingTest.java
src/main/java/org/exist/xmldb/LocalBinaryResource.java
+ src/main/java/org/exist/xmldb/LocalCollection.java
src/main/java/org/exist/xmldb/LocalResourceSet.java
+ src/main/java/org/exist/xmldb/LocalRestoreService.java
src/main/java/org/exist/xmldb/LocalXMLResource.java
src/main/java/org/exist/xmldb/LocalXPathQueryService.java
src/main/java/org/exist/xmldb/RemoteBinaryResource.java
+ src/main/java/org/exist/xmldb/RemoteCollection.java
+ src/test/java/org/exist/xmldb/RemoteCollectionTest.java
src/test/java/org/exist/xmldb/RemoteDOMTest.java
+ src/test/java/org/exist/xmldb/RemoteQueryTest.java
src/main/java/org/exist/xmldb/RemoteResourceSet.java
src/main/java/org/exist/xmldb/RemoteRestoreService.java
src/main/java/org/exist/xmldb/RemoteXMLResource.java
@@ -1772,6 +1970,7 @@
src/main/java/org/exist/xmlrpc/RpcAPI.java
src/main/java/org/exist/xmlrpc/RpcConnection.java
src/main/java/org/exist/xmlrpc/XmlRpcExtensionConstants.java
+ src/test/java/org/exist/xmlrpc/XmlRpcTest.java
src/main/java/org/exist/xqj/Marshaller.java
src/test/java/org/exist/xqj/MarshallerTest.java
src/main/java/org/exist/xquery/AbstractInternalModule.java
@@ -1785,6 +1984,7 @@
src/main/java/org/exist/xquery/DynamicCardinalityCheck.java
src/main/java/org/exist/xquery/DynamicTypeCheck.java
src/main/java/org/exist/xquery/DynamicVariable.java
+ src/test/java/org/exist/xquery/EmbeddedBinariesTest.java
src/test/java/org/exist/xquery/EmbeddedBinariesTest.java.java
src/main/java/org/exist/xquery/ErrorCodes.java
src/main/java/org/exist/xquery/ExternalModuleImpl.java
@@ -1797,6 +1997,7 @@
src/main/java/org/exist/xquery/JavaBinding.java
src/test/resources-filtered/org/exist/xquery/JavaBindingTest.conf.xml
src/test/java/org/exist/xquery/JavaBindingTest.java
+ src/test/java/org/exist/xquery/LexerTest.java
src/main/java/org/exist/xquery/LocationStep.java
src/main/java/org/exist/xquery/Materializable.java
src/main/java/org/exist/xquery/Module.java
@@ -1808,12 +2009,14 @@
src/main/java/org/exist/xquery/PerformanceStatsImpl.java
src/test/java/org/exist/xquery/RestBinariesTest.java
src/test/java/org/exist/xquery/StoredModuleTest.java
+ src/test/java/org/exist/xquery/TransformTest.java
src/main/java/org/exist/xquery/TryCatchExpression.java
src/main/java/org/exist/xquery/UserDefinedFunction.java
src/main/java/org/exist/xquery/Variable.java
src/main/java/org/exist/xquery/VariableDeclaration.java
src/main/java/org/exist/xquery/VariableImpl.java
src/main/java/org/exist/xquery/VariableReference.java
+ src/test/java/org/exist/xquery/VariablesTest.java
src/test/java/org/exist/xquery/WatchdogTest.java
src/test/java/org/exist/xquery/WindowClauseTest.java
src/test/java/org/exist/xquery/XmldbBinariesTest.java
@@ -1823,6 +2026,7 @@
src/test/java/org/exist/xquery/XPathUtilTest.java
src/main/java/org/exist/xquery/XQueryContext.java
src/test/java/org/exist/xquery/XQueryContextAttributesTest.java
+ src/test/java/org/exist/xquery/XQueryDeclareContextItemTest.java
src/test/java/org/exist/xquery/XQueryFunctionsTest.java
src/main/java/org/exist/xquery/XQueryProcessingInstruction.java
src/test/java/org/exist/xquery/XQueryProcessingInstructionTest.java
@@ -1941,10 +2145,17 @@
src/main/java/org/exist/xquery/functions/fn/transform/Options.java
src/main/java/org/exist/xquery/functions/fn/transform/Transform.java
src/main/java/org/exist/xquery/functions/fn/transform/TreeUtils.java
+ src/test/java/org/exist/xquery/functions/inspect/InspectModuleTest.java
src/main/java/org/exist/xquery/functions/integer/WordPicture.java
src/main/java/org/exist/xquery/functions/map/MapExpr.java
src/main/java/org/exist/xquery/functions/map/MapType.java
+ src/main/java/org/exist/xquery/functions/request/GetData.java
+ src/test/java/org/exist/xquery/functions/request/GetData2Test.java
+ src/test/java/org/exist/xquery/functions/request/GetDataTest.java
src/test/java/org/exist/xquery/functions/request/GetHeaderTest.java
+ src/test/java/org/exist/xquery/functions/request/GetParameterTest.java
+ src/test/java/org/exist/xquery/functions/request/PatchTest.java
+ src/main/java/org/exist/xquery/functions/response/Stream.java
src/test/java/org/exist/xquery/functions/securitymanager/AccountMetadataFunctionsTest.java
src/test/java/org/exist/xquery/functions/securitymanager/GetPermissionsTest.java
src/test/java/org/exist/xquery/functions/securitymanager/GroupManagementFunctionRemoveGroupTest.java
@@ -1958,6 +2169,7 @@
src/main/java/org/exist/xquery/functions/system/FunctionAvailable.java
src/test/java/org/exist/xquery/functions/system/GetRunningXQueriesTest.java
src/main/java/org/exist/xquery/functions/system/GetUptime.java
+ src/main/java/org/exist/xquery/functions/system/Restore.java
src/main/java/org/exist/xquery/functions/system/Shutdown.java
src/main/java/org/exist/xquery/functions/system/SystemModule.java
src/main/java/org/exist/xquery/functions/system/TriggerSystemTask.java
@@ -1968,6 +2180,8 @@
src/main/java/org/exist/xquery/functions/util/BuiltinFunctions.java
src/main/java/org/exist/xquery/functions/util/DescribeFunction.java
src/main/java/org/exist/xquery/functions/util/Eval.java
+ src/test/java/org/exist/xquery/functions/util/EvalTest.java
+ src/test/java/org/exist/xquery/functions/util/ExpandTest.java
src/main/java/org/exist/xquery/functions/util/FunctionFunction.java
src/main/java/org/exist/xquery/functions/util/LogFunction.java
src/main/java/org/exist/xquery/functions/util/ModuleInfo.java
@@ -1983,7 +2197,10 @@
src/test/java/org/exist/xquery/functions/xmldb/AbstractXMLDBTest.java
src/test/java/org/exist/xquery/functions/xmldb/DbStore2Test.java
src/test/java/org/exist/xquery/functions/xmldb/XMLDBAuthenticateTest.java
+ src/main/java/org/exist/xquery/functions/xmldb/XMLDBGetMimeType.java
+ src/main/java/org/exist/xquery/functions/xmldb/XMLDBLoadFromPattern.java
src/main/java/org/exist/xquery/functions/xmldb/XMLDBModule.java
+ src/main/java/org/exist/xquery/functions/xmldb/XMLDBSetMimeType.java
src/main/java/org/exist/xquery/functions/xmldb/XMLDBStore.java
src/test/java/org/exist/xquery/functions/xmldb/XMLDBStoreTest.java
src/main/java/org/exist/xquery/functions/xmldb/XMLDBXUpdate.java
@@ -1994,6 +2211,7 @@
src/test/java/org/exist/xquery/update/AbstractUpdateTest.java
src/test/java/org/exist/xquery/update/IndexIntegrationTest.java
src/test/java/org/exist/xquery/update/UpdateInsertTest.java
+ src/test/java/org/exist/xquery/update/UpdateInsertTriggersDefragTest.java
src/test/java/org/exist/xquery/update/UpdateReplaceTest.java
src/test/java/org/exist/xquery/update/UpdateValueTest.java
src/main/java/org/exist/xquery/util/ExpressionDumper.java
@@ -2056,6 +2274,8 @@
src/main/java/org/exist/xupdate/Update.java
src/main/java/org/exist/xupdate/XUpdateProcessor.java
src/test/java/org/exist/xupdate/XUpdateTest.java
+ src/main/resources/xyz/elemental/mediatype/media-type-mappings.xml
+ src/main/resources/xyz/elemental/mediatype/mime.types
@@ -2129,9 +2349,9 @@ The original license statement is also included below.]]>
- ${project.parent.relativePath}/FDB-backport-LGPL-21-ONLY-license.template.txt
+ ${project.parent.relativePath}/FDB-backport-to-existdb-LGPL-21-ONLY-license.template.txt
src/test/xquery/binary-value.xqm
src/test/xquery/instance-of.xqm
@@ -2228,9 +2448,22 @@ The original license statement is also included below.]]>
- FDB-backport-BSD-3-license.template.txt
+ ${project.parent.relativePath}/../elemental-parent/FDB-backport-to-EDB-LGPL-21-ONLY-license.template.txt
+
+ src/main/java/org/exist/mediatype/MediaTypeService.java
+ src/main/java/org/exist/mediatype/MediaTypeUtil.java
+ src/main/resources/xyz/elemental/mediatype/media-type-mappings.xml
+ src/main/resources/xyz/elemental/mediatype/mime.types
+
+
+
+
+
+ FDB-backport-to-existdb-BSD-3-license.template.txt
src/main/java/org/exist/util/CodePointString.java
src/test/java/org/exist/util/CodePointStringTest.java
@@ -2240,12 +2473,12 @@ The original license statement is also included below.]]>
- FDB-backport-BSD-3-license.template.txt
+ FDB-backport-to-existdb-BSD-3-license.template.txt
BX-BSD-3-license.template.txt
@@ -2346,6 +2579,23 @@ The BaseX Team. The original license statement is also included below.]]>
+
+ org.jvnet.jaxb
+ jaxb-maven-plugin
+
+ src/main/xjb
+ src/main/xsd
+
+
+
+ generate-jaxb-objects
+
+ generate
+
+
+
+
+
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/exist-core/src/main/java/org/exist/backup/Backup.java b/exist-core/src/main/java/org/exist/backup/Backup.java
index e000fa6d93..4ab112b1d3 100644
--- a/exist-core/src/main/java/org/exist/backup/Backup.java
+++ b/exist-core/src/main/java/org/exist/backup/Backup.java
@@ -1,4 +1,28 @@
/*
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ * The original license header is included below.
+ *
+ * =====================================================================
+ *
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
@@ -421,7 +445,7 @@ private void backup(final Set seenBlobIds, final Collection current, fin
}
attr.addAttribute(Namespaces.EXIST_NS, "filename", "filename", "CDATA", filename);
- attr.addAttribute(Namespaces.EXIST_NS, "mimetype", "mimetype", "CDATA", encode(((EXistResource) resource).getMimeType()));
+ attr.addAttribute(Namespaces.EXIST_NS, "mimetype", "mimetype", "CDATA", encode(((EXistResource) resource).getMediaType()));
if (XML_RESOURCE.equals(resourceType)) {
diff --git a/exist-core/src/main/java/org/exist/backup/CreateBackupDialog.java b/exist-core/src/main/java/org/exist/backup/CreateBackupDialog.java
index 189d06b3b9..5d2b92bef4 100644
--- a/exist-core/src/main/java/org/exist/backup/CreateBackupDialog.java
+++ b/exist-core/src/main/java/org/exist/backup/CreateBackupDialog.java
@@ -1,4 +1,28 @@
/*
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ * The original license header is included below.
+ *
+ * =====================================================================
+ *
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
@@ -22,12 +46,14 @@
package org.exist.backup;
import org.exist.client.Messages;
-import org.exist.client.MimeTypeFileFilter;
+import org.exist.client.MediaTypeFileFilter;
import org.exist.security.PermissionDeniedException;
import org.exist.xmldb.XmldbURI;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.XMLDBException;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeResolver;
import javax.swing.*;
import java.awt.*;
@@ -49,12 +75,13 @@ public class CreateBackupDialog extends JPanel {
final String passwd;
Path backupDir;
final String defaultSelectedCollection;
+ private final MediaTypeResolver mediaTypeResolver;
- public CreateBackupDialog(final String uri, final String user, final String passwd, final Path backupDir) throws HeadlessException {
- this(uri, user, passwd, backupDir, null);
+ public CreateBackupDialog(final String uri, final String user, final String passwd, final Path backupDir, final MediaTypeResolver mediaTypeResolver) throws HeadlessException {
+ this(uri, user, passwd, backupDir, null, mediaTypeResolver);
}
- public CreateBackupDialog(final String uri, final String user, final String passwd, final Path backupDir, final String defaultSelectedCollection) throws HeadlessException {
+ public CreateBackupDialog(final String uri, final String user, final String passwd, final Path backupDir, final String defaultSelectedCollection, final MediaTypeResolver mediaTypeResolver) throws HeadlessException {
super(false);
this.uri = uri;
@@ -62,6 +89,7 @@ public CreateBackupDialog(final String uri, final String user, final String pass
this.passwd = passwd;
this.backupDir = backupDir;
this.defaultSelectedCollection = defaultSelectedCollection;
+ this.mediaTypeResolver = mediaTypeResolver;
setupComponents();
setSize(new Dimension(350, 200));
@@ -147,7 +175,8 @@ private void actionSelect() {
final JFileChooser chooser = new JFileChooser();
chooser.setMultiSelectionEnabled(false);
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
- chooser.addChoosableFileFilter(new MimeTypeFileFilter("application/zip"));
+ final MediaType mediaType = mediaTypeResolver.fromString(MediaType.APPLICATION_ZIP);
+ chooser.addChoosableFileFilter(new MediaTypeFileFilter(mediaType));
chooser.setSelectedFile(Paths.get("eXist-backup.zip").toFile());
chooser.setCurrentDirectory(backupDir.toFile());
diff --git a/exist-core/src/main/java/org/exist/backup/ExportGUI.java b/exist-core/src/main/java/org/exist/backup/ExportGUI.java
index 0454f591ed..d50d380164 100644
--- a/exist-core/src/main/java/org/exist/backup/ExportGUI.java
+++ b/exist-core/src/main/java/org/exist/backup/ExportGUI.java
@@ -53,14 +53,14 @@
import org.exist.storage.DBBroker;
import org.exist.storage.txn.Txn;
import org.exist.util.Configuration;
-import org.exist.util.MimeTable;
-import org.exist.util.MimeType;
import org.exist.util.OSUtil;
import org.exist.util.SystemExitCodes;
import org.exist.xquery.TerminatedException;
import se.softhouse.jargo.Argument;
import se.softhouse.jargo.ArgumentException;
import se.softhouse.jargo.CommandLineParser;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.StorageType;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
@@ -437,19 +437,20 @@ private void btnConfSelectActionPerformed(final java.awt.event.ActionEvent evt)
.toFile());
chooser.setCurrentDirectory(dir.resolve("etc").toFile());
chooser.setFileFilter(new FileFilter() {
+ @Override
public boolean accept(final File f) {
if (f.isDirectory()) {
return (true);
}
- final MimeType mime = MimeTable.getInstance().getContentTypeFor(f.getName());
+ final MediaType mediaType = pool.getMediaTypeService().getMediaTypeResolver().fromFileName(f.toPath());
- if (mime == null) {
+ if (mediaType == null) {
return false;
}
- return mime.isXMLType();
+ return mediaType.getStorageType() == StorageType.XML;
}
-
+ @Override
public String getDescription() {
return ("Database XML configuration file");
}
diff --git a/exist-core/src/main/java/org/exist/backup/Main.java b/exist-core/src/main/java/org/exist/backup/Main.java
index 7e15f31ea5..f63f98b6f2 100644
--- a/exist-core/src/main/java/org/exist/backup/Main.java
+++ b/exist-core/src/main/java/org/exist/backup/Main.java
@@ -46,6 +46,7 @@
package org.exist.backup;
import org.exist.client.ClientFrame;
+import org.exist.mediatype.MediaTypeUtil;
import org.exist.start.CompatibleJavaVersionCheck;
import org.exist.start.StartException;
import org.exist.util.ConfigurationHelper;
@@ -58,7 +59,9 @@
import org.xmldb.api.base.Database;
import org.xmldb.api.base.XMLDBException;
import se.softhouse.jargo.*;
+import xyz.elemental.mediatype.MediaTypeResolver;
+import javax.annotation.Nullable;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
@@ -223,12 +226,17 @@ public static void process(final ParsedArguments arguments) {
return;
}
+ // load MediaTypeResolver
+ final Optional existHome = ConfigurationHelper.getExistHome();
+ @Nullable final Path applicationConfigDir = existHome.map(p -> p.resolve("etc")).filter(Files::exists).orElse(null);
+ @Nullable final MediaTypeResolver mediaTypeResolver = MediaTypeUtil.newMediaTypeResolver(applicationConfigDir);
+
// process
if (backupCollection.isPresent()) {
String collection = backupCollection.get();
if (collection.isEmpty()) {
if (guiMode) {
- final CreateBackupDialog dialog = new CreateBackupDialog(properties.getProperty(URI_PROP, DEFAULT_URI), properties.getProperty(USER_PROP, DEFAULT_USER), properties.getProperty(PASSWORD_PROP, DEFAULT_PASSWORD), Paths.get(preferences.get("directory.backup", System.getProperty("user.dir"))));
+ final CreateBackupDialog dialog = new CreateBackupDialog(properties.getProperty(URI_PROP, DEFAULT_URI), properties.getProperty(USER_PROP, DEFAULT_USER), properties.getProperty(PASSWORD_PROP, DEFAULT_PASSWORD), Paths.get(preferences.get("directory.backup", System.getProperty("user.dir"))), mediaTypeResolver);
if (JOptionPane.showOptionDialog(null, dialog, "Create Backup", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null) == JOptionPane.YES_OPTION) {
collection = dialog.getCollection();
diff --git a/exist-core/src/main/java/org/exist/backup/Restore.java b/exist-core/src/main/java/org/exist/backup/Restore.java
index 7b38622b11..b66debebf9 100644
--- a/exist-core/src/main/java/org/exist/backup/Restore.java
+++ b/exist-core/src/main/java/org/exist/backup/Restore.java
@@ -1,4 +1,28 @@
/*
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ * The original license header is included below.
+ *
+ * =====================================================================
+ *
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
@@ -36,6 +60,7 @@
import org.exist.util.XMLReaderPool;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
+import xyz.elemental.mediatype.MediaTypeResolver;
import javax.annotation.Nullable;
import java.io.IOException;
@@ -57,7 +82,7 @@ public class Restore {
private static final byte[] ZIP_FILE_MAGIC_NUMBER = {0x50, 0x4B, 0x03, 0x04};
public void restore(final DBBroker broker, @Nullable final Txn transaction, final String newAdminPass, final Path f,
- final RestoreListener listener, final boolean overwriteApps) throws EXistException, IOException, SAXException, PermissionDeniedException {
+ final RestoreListener listener, final boolean overwriteApps, final MediaTypeResolver mediaTypeResolver) throws EXistException, IOException, SAXException, PermissionDeniedException {
//set the admin password
if (newAdminPass != null) {
diff --git a/exist-core/src/main/java/org/exist/backup/SystemExport.java b/exist-core/src/main/java/org/exist/backup/SystemExport.java
index c403e170b2..d9eae3b9cb 100644
--- a/exist-core/src/main/java/org/exist/backup/SystemExport.java
+++ b/exist-core/src/main/java/org/exist/backup/SystemExport.java
@@ -93,6 +93,7 @@
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.NamespaceSupport;
+import xyz.elemental.mediatype.MediaType;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
@@ -565,10 +566,10 @@ private void exportDocument(final BackupWriter output, final Date date, final Ba
}
attr.addAttribute(Namespaces.EXIST_NS, "filename", "filename", "CDATA", Backup.encode(URIUtils.urlDecodeUtf8(doc.getFileURI())));
- String mimeType = "application/xml";
+ String mimeType = MediaType.APPLICATION_XML;
- if (doc.getMimeType() != null) {
- mimeType = Backup.encode(doc.getMimeType());
+ if (doc.getMediaType() != null) {
+ mimeType = Backup.encode(doc.getMediaType());
}
attr.addAttribute(Namespaces.EXIST_NS, "mimetype", "mimetype", "CDATA", mimeType);
diff --git a/exist-core/src/main/java/org/exist/backup/restore/AbstractRestoreHandler.java b/exist-core/src/main/java/org/exist/backup/restore/AbstractRestoreHandler.java
index 218efd7237..34fe394668 100644
--- a/exist-core/src/main/java/org/exist/backup/restore/AbstractRestoreHandler.java
+++ b/exist-core/src/main/java/org/exist/backup/restore/AbstractRestoreHandler.java
@@ -1,4 +1,28 @@
/*
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ * The original license header is included below.
+ *
+ * =====================================================================
+ *
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
@@ -55,6 +79,10 @@
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeResolver;
+import xyz.elemental.mediatype.StorageType;
+import xyz.elemental.mediatype.impl.MediaTypeImpl;
import javax.annotation.Nullable;
import java.io.IOException;
@@ -63,6 +91,7 @@
import static com.evolvedbinary.j8fu.tuple.Tuple.Tuple;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.exist.util.StringUtil.isNullOrEmpty;
/**
* SAX Content Handler that can act upon
@@ -89,7 +118,6 @@ public abstract class AbstractRestoreHandler extends DefaultHandler {
@Nullable private final Txn transaction;
private final BackupDescriptor descriptor;
private final RestoreListener listener;
-
@Nullable private final Set pathsToIgnore;
//handler state
@@ -312,7 +340,7 @@ private DeferredPermission restoreResourceEntry(final Attributes attributes) thr
final boolean xmlType = Optional.ofNullable(attributes.getValue("type")).filter(s -> s.equals("XMLResource")).isPresent();
final String filename = getAttr(attributes, "filename", commonAttributes.name);
- @Nullable final String mimeTypeStr = attributes.getValue("mimetype");
+ @Nullable final String mediaTypeStr = attributes.getValue("mimetype");
@Nullable final String dateModifiedStr = attributes.getValue("modified");
@Nullable final String publicId = attributes.getValue("publicid");
@Nullable final String systemId = attributes.getValue("systemid");
@@ -343,12 +371,19 @@ private DeferredPermission restoreResourceEntry(final Attributes attributes) thr
}
}
- final MimeType mimeType;
- if (mimeTypeStr == null || mimeTypeStr.trim().isEmpty()) {
- mimeType = xmlType ? MimeType.XML_TYPE : MimeType.BINARY_TYPE;
- listener.warn("Missing mimetype attribute in the backup __contents__.xml file for: " + commonAttributes.name + ", assuming: " + mimeType);
+ final MediaTypeResolver mediaTypeResolver = broker.getBrokerPool().getMediaTypeService().getMediaTypeResolver();
+
+ MediaType mediaType;
+ if (isNullOrEmpty(mediaTypeStr)) {
+ mediaType = xmlType ? mediaTypeResolver.fromString(MediaType.APPLICATION_XML) : mediaTypeResolver.forUnknown();
+ listener.warn("Missing mimetype attribute in the backup __contents__.xml file for: " + commonAttributes.name + ", assuming: " + mediaType);
} else {
- mimeType = new MimeType(mimeTypeStr.trim(), xmlType ? MimeType.XML : MimeType.BINARY);
+ mediaType = mediaTypeResolver.fromString(mediaTypeStr.trim());
+ if (xmlType && mediaType.getStorageType() != StorageType.XML) {
+ mediaType = MediaTypeImpl.builder(mediaTypeStr.trim(), StorageType.XML).build();
+ } else if ((!xmlType) && mediaType.getStorageType() != StorageType.BINARY) {
+ mediaType = MediaTypeImpl.builder(mediaTypeStr.trim(), StorageType.BINARY).build();
+ }
}
Date dateCreated = null;
@@ -385,7 +420,7 @@ private DeferredPermission restoreResourceEntry(final Attributes attributes) thr
try (final Collection collection = broker.openCollection(currentCollectionUri, Lock.LockMode.WRITE_LOCK);
final ManagedDocumentLock docLock = broker.getBrokerPool().getLockManager().acquireDocumentWriteLock(docUri)) {
- broker.storeDocument(transaction, docName, is, mimeType, dateCreated, dateModified, null, docType, null, collection);
+ broker.storeDocument(transaction, docName, is, mediaType, dateCreated, dateModified, null, docType, null, collection);
validated = true;
notifyStartDocumentRestore(docUri, attributes);
@@ -572,6 +607,7 @@ private static String getAttr(final Attributes atts, final String name, final St
* @param descriptor the backup descriptor to start restoring from
* @param listener the listener to report restore events to
* @param pathsToIgnore database paths to ignore in the backup
+ *
* @return a new restore handler
*/
protected abstract AbstractRestoreHandler newSelf(final DBBroker broker, @Nullable final Txn transaction,
diff --git a/exist-core/src/main/java/org/exist/backup/xquery/RetrieveBackup.java b/exist-core/src/main/java/org/exist/backup/xquery/RetrieveBackup.java
index 64a54d8746..c481831bb5 100644
--- a/exist-core/src/main/java/org/exist/backup/xquery/RetrieveBackup.java
+++ b/exist-core/src/main/java/org/exist/backup/xquery/RetrieveBackup.java
@@ -1,4 +1,28 @@
/*
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ * The original license header is included below.
+ *
+ * =====================================================================
+ *
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
@@ -31,6 +55,7 @@
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.SequenceType;
import org.exist.xquery.value.Type;
+import xyz.elemental.mediatype.MediaType;
import java.io.IOException;
import java.io.OutputStream;
@@ -101,7 +126,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence ) thr
throw new XPathException(this, signature.toString() + " can only be used within the EXistServlet or XQueryServlet");
}
- response.setContentType("application/zip");
+ response.setContentType(MediaType.APPLICATION_ZIP);
response.setHeader("Content-Length", String.valueOf(FileUtils.sizeQuietly(backupFile)));
try {
try(final OutputStream os = response.getOutputStream()) {
diff --git a/exist-core/src/main/java/org/exist/client/ClientFrame.java b/exist-core/src/main/java/org/exist/client/ClientFrame.java
index d5e722a432..52547f6fbb 100644
--- a/exist-core/src/main/java/org/exist/client/ClientFrame.java
+++ b/exist-core/src/main/java/org/exist/client/ClientFrame.java
@@ -58,7 +58,6 @@
import org.exist.security.internal.aider.SimpleACLPermissionAider;
import org.exist.storage.serializers.EXistOutputKeys;
import org.exist.util.FileUtils;
-import org.exist.util.MimeTable;
import org.exist.util.SystemExitCodes;
import org.exist.util.crypto.digest.DigestType;
import org.exist.util.crypto.digest.MessageDigest;
@@ -73,7 +72,11 @@
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.XMLResource;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeResolver;
+import xyz.elemental.mediatype.StorageType;
+import javax.annotation.Nullable;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.filechooser.FileFilter;
@@ -298,7 +301,7 @@ private void setupComponents() {
// shell window
doc = new DefaultStyledDocument();
shell = new JTextPane(doc);
- shell.setContentType("text/plain; charset=UTF-8"); //$NON-NLS-1$
+ shell.setContentType(MediaType.TEXT_PLAIN + "; charset=UTF-8"); //$NON-NLS-1$
shell.setFont(new Font("Monospaced", Font.PLAIN, 12)); //$NON-NLS-1$
shell.setMargin(new Insets(7, 5, 7, 5));
shell.addKeyListener(this);
@@ -998,8 +1001,8 @@ private void uploadAction(final ActionEvent ev) {
final JFileChooser chooser = new JFileChooser(preferences.get("directory.last", System.getProperty("user.dir")));
chooser.setMultiSelectionEnabled(true);
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
- chooser.addChoosableFileFilter(new BinaryFileFilter());
- chooser.addChoosableFileFilter(new XMLFileFilter());
+ chooser.addChoosableFileFilter(new BinaryFileFilter(client.getMediaTypeResolver()));
+ chooser.addChoosableFileFilter(new XMLFileFilter(client.getMediaTypeResolver()));
if (chooser.showDialog(this, Messages.getString("ClientFrame.146")) == JFileChooser.APPROVE_OPTION) { //$NON-NLS-1$
// remember directory in preferences
preferences.put("directory.last", chooser.getCurrentDirectory().getAbsolutePath());
@@ -1053,7 +1056,8 @@ private void backupAction(final ActionEvent ev) {
properties.getProperty(InteractiveClient.USER, SecurityManager.DBA_USER),
properties.getProperty(InteractiveClient.PASSWORD, null),
Paths.get(preferences.get("directory.backup", System.getProperty("user.home"))),
- defaultSelectedCollection
+ defaultSelectedCollection,
+ client.getMediaTypeResolver()
);
if (JOptionPane.showOptionDialog(this, dialog, Messages.getString("ClientFrame.157"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null) == JOptionPane.YES_OPTION) {
@@ -1320,7 +1324,7 @@ private void setPermAction(final ActionEvent ev) throws PermissionDeniedExceptio
final Resource res = collection.getResource(thisName.toString());
thisCreated = DATE_TIME_FORMATTER.format(res.getCreationTime());
thisModified = DATE_TIME_FORMATTER.format(res.getLastModificationTime());
- thisMimeType = ((EXistResource) res).getMimeType();
+ thisMimeType = ((EXistResource) res).getMediaType();
if (res instanceof EXistBinaryResource) {
final MessageDigest messageDigest = ((EXistBinaryResource) res).getContentDigest(DigestType.BLAKE_256);
thisMessageDigestType = messageDigest.getDigestType().getCommonNames()[0];
@@ -1540,7 +1544,7 @@ public void mouseClicked(final MouseEvent e) {
try {
final Resource doc = client.retrieve(resource.getName(), properties.getProperty(OutputKeys.INDENT, "yes")); //$NON-NLS-1$
- if ("application/xquery".equals(((EXistResource) doc).getMimeType())) {
+ if (MediaType.APPLICATION_XQUERY.equals(((EXistResource) doc).getMediaType())) {
final Collection collection = client.getCollection();
final QueryDialog dialog = new QueryDialog(client, collection, doc, properties);
dialog.setVisible(true);
@@ -1887,46 +1891,46 @@ public void mouseReleased(final MouseEvent e) {
}
static class BinaryFileFilter extends FileFilter {
+ private final MediaTypeResolver mediaTypeResolver;
+
+ public BinaryFileFilter(final MediaTypeResolver mediaTypeResolver) {
+ this.mediaTypeResolver = mediaTypeResolver;
+ }
- /* (non-Javadoc)
- * @see javax.swing.filechooser.FileFilter#getDescription()
- */
@Override
public String getDescription() {
return Messages.getString("ClientFrame.220"); //$NON-NLS-1$
}
- /* (non-Javadoc)
- * @see javax.swing.filechooser.FileFilter#accept(java.io.File)
- */
@Override
public boolean accept(final File f) {
if (f.isDirectory()) {
return true;
}
- return !MimeTable.getInstance().isXMLContent(f.getName());
+ @Nullable MediaType mediaType = mediaTypeResolver.fromFileName(f.toPath().getFileName());
+ return mediaType == null || mediaType.getStorageType() != StorageType.XML;
}
}
static class XMLFileFilter extends FileFilter {
+ private final MediaTypeResolver mediaTypeResolver;
+
+ public XMLFileFilter(final MediaTypeResolver mediaTypeResolver) {
+ this.mediaTypeResolver = mediaTypeResolver;
+ }
- /* (non-Javadoc)
- * @see javax.swing.filechooser.FileFilter#getDescription()
- */
@Override
public String getDescription() {
return Messages.getString("ClientFrame.221"); //$NON-NLS-1$
}
- /* (non-Javadoc)
- * @see javax.swing.filechooser.FileFilter#accept(java.io.File)
- */
@Override
public boolean accept(final File f) {
if (f.isDirectory()) {
return true;
}
- return MimeTable.getInstance().isXMLContent(f.getName());
+ @Nullable MediaType mediaType = mediaTypeResolver.fromFileName(f.toPath().getFileName());
+ return mediaType != null && mediaType.getStorageType() == StorageType.XML;
}
}
@@ -1981,7 +1985,7 @@ private List getFilesWin32(final Transferable transferable) throws Unsuppo
private List getFilesUnix(final Transferable transferable) throws ClassNotFoundException, UnsupportedFlavorException, IOException, URISyntaxException {
List files = null;
- final DataFlavor unixFileDataFlavour = new DataFlavor("text/uri-list;class=java.lang.String");
+ final DataFlavor unixFileDataFlavour = new DataFlavor(MediaType.TEXT_URI_LIST + ";class=java.lang.String");
final String data = (String) transferable.getTransferData(unixFileDataFlavour);
for (final StringTokenizer st = new StringTokenizer(data, "\r\n"); st.hasMoreTokens(); ) {
final String token = st.nextToken().trim();
diff --git a/exist-core/src/main/java/org/exist/client/InteractiveClient.java b/exist-core/src/main/java/org/exist/client/InteractiveClient.java
index 3346f69fbd..fbcfd5de0b 100644
--- a/exist-core/src/main/java/org/exist/client/InteractiveClient.java
+++ b/exist-core/src/main/java/org/exist/client/InteractiveClient.java
@@ -65,6 +65,7 @@
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import javax.annotation.Nullable;
import javax.swing.ImageIcon;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
@@ -76,6 +77,7 @@
import org.apache.tools.ant.DirectoryScanner;
import org.exist.SystemProperties;
import org.exist.dom.persistent.XMLUtil;
+import org.exist.mediatype.MediaTypeUtil;
import org.exist.security.Account;
import org.exist.security.Group;
import org.exist.security.Permission;
@@ -110,8 +112,12 @@
import org.xmldb.api.base.*;
import org.xmldb.api.base.Collection;
import org.xmldb.api.modules.BinaryResource;
+import org.xmldb.api.modules.XMLResource;
import org.xmldb.api.modules.XUpdateQueryService;
import se.softhouse.jargo.ArgumentException;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeResolver;
+import xyz.elemental.mediatype.StorageType;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.time.ZoneOffset.UTC;
@@ -226,6 +232,8 @@ public InteractiveClient(CommandlineOptions options) {
this.options = options;
}
+ private MediaTypeResolver mediaTypeResolver = null;
+
/**
* Display help on commands
*/
@@ -1311,21 +1319,25 @@ private void reindex() throws XMLDBException {
private void storeBinary(final String fileName) throws XMLDBException {
final Path file = Paths.get(fileName).normalize();
if (Files.isReadable(file)) {
- final MimeType mime = MimeTable.getInstance().getContentTypeFor(FileUtils.fileName(file));
+ @Nullable final MediaType mediaType = mediaTypeResolver.fromFileName(FileUtils.fileName(file));
try (final BinaryResource resource = current.createResource(FileUtils.fileName(file), BinaryResource.class)) {
resource.setContent(file);
- ((EXistResource) resource).setMimeType(mime == null ? "application/octet-stream" : mime.getName());
+ ((EXistResource) resource).setMediaType(mediaType == null ? mediaTypeResolver.forUnknown().getIdentifier() : mediaType.getIdentifier());
current.storeResource(resource);
}
}
}
+ MediaTypeResolver getMediaTypeResolver() {
+ return mediaTypeResolver;
+ }
+
private synchronized boolean findRecursive(final Collection collection, final Path dir, final XmldbURI base) throws XMLDBException {
Collection c;
EXistCollectionManagementService mgtService;
//The XmldbURIs here aren't really used...
XmldbURI next;
- MimeType mimeType;
+ @Nullable MediaType mediaType = null;
try {
final List files = FileUtils.list(dir);
@@ -1348,15 +1360,15 @@ private synchronized boolean findRecursive(final Collection collection, final Pa
findRecursive(c, file, next);
} else {
final long start1 = System.currentTimeMillis();
- mimeType = MimeTable.getInstance().getContentTypeFor(FileUtils.fileName(file));
- if (mimeType == null) {
+ mediaType = mediaTypeResolver.fromFileName(FileUtils.fileName(file));
+ if (mediaType == null) {
messageln("File " + FileUtils.fileName(file) + " has an unknown suffix. Cannot determine file type.");
- mimeType = MimeType.BINARY_TYPE;
+ mediaType = mediaTypeResolver.forUnknown();
}
- try (final Resource document = collection.createResource(FileUtils.fileName(file), mimeType.getXMLDBType())) {
+ try (final Resource document = collection.createResource(FileUtils.fileName(file), toResourceTypeClass(mediaType))) {
message("storing document " + FileUtils.fileName(file) + " (" + i + " of " + files.size() + ") " + "...");
document.setContent(file);
- ((EXistResource) document).setMimeType(mimeType.getName());
+ ((EXistResource) document).setMediaType(mediaType.getIdentifier());
collection.storeResource(document);
++filesCount;
messageln(" " + FileUtils.sizeQuietly(file) + " bytes in " + (System.currentTimeMillis() - start1) + "ms.");
@@ -1373,6 +1385,10 @@ private synchronized boolean findRecursive(final Collection collection, final Pa
}
}
+ private static Class extends Resource> toResourceTypeClass(final MediaType mediaType) {
+ return mediaType.getStorageType() == StorageType.XML ? XMLResource.class : BinaryResource.class;
+ }
+
/**
* Stores given Resource
*
@@ -1418,20 +1434,20 @@ protected synchronized boolean parse(final Path file) throws XMLDBException {
final long start0 = System.currentTimeMillis();
long bytes = 0;
- MimeType mimeType;
+ @Nullable MediaType mediaType = null;
for (int i = 0; i < files.size(); i++) {
if (Files.isDirectory(files.get(i))) {
continue;
}
final long start = System.currentTimeMillis();
- mimeType = MimeTable.getInstance().getContentTypeFor(FileUtils.fileName(files.get(i)));
- if (mimeType == null) {
- mimeType = MimeType.BINARY_TYPE;
+ mediaType = mediaTypeResolver.fromFileName(FileUtils.fileName(files.get(i)));
+ if (mediaType == null) {
+ mediaType = mediaTypeResolver.forUnknown();
}
- try (final Resource document = current.createResource(FileUtils.fileName(files.get(i)), mimeType.getXMLDBType())) {
+ try (final Resource document = current.createResource(FileUtils.fileName(files.get(i)), toResourceTypeClass(mediaType))) {
message("storing document " + FileUtils.fileName(files.get(i)) + " (" + (i + 1) + " of " + files.size() + ") ...");
document.setContent(files.get(i));
- ((EXistResource) document).setMimeType(mimeType.getName());
+ ((EXistResource) document).setMediaType(mediaType.getIdentifier());
current.storeResource(document);
messageln(DONE);
messageln("parsing " + FileUtils.sizeQuietly(files.get(i)) + " bytes took " + (System.currentTimeMillis() - start) + "ms." + EOL);
@@ -1453,7 +1469,7 @@ private synchronized boolean findGZipRecursive(final Collection collection, fina
EXistCollectionManagementService mgtService;
//The XmldbURIs here aren't really used...
XmldbURI next;
- MimeType mimeType;
+ @Nullable MediaType mediaType = null;
int i = 0;
for (final Path file : files) {
i++;
@@ -1485,15 +1501,15 @@ private synchronized boolean findGZipRecursive(final Collection collection, fina
break;
}
}
- mimeType = MimeTable.getInstance().getContentTypeFor(localName);
- if (mimeType == null) {
+ mediaType = mediaTypeResolver.fromFileName(localName);
+ if (mediaType == null) {
messageln("File " + compressedName + " has an unknown suffix. Cannot determine file type.");
- mimeType = MimeType.BINARY_TYPE;
+ mediaType = mediaTypeResolver.forUnknown();
}
- try (final Resource document = collection.createResource(compressedName, mimeType.getXMLDBType())) {
+ try (final Resource document = collection.createResource(compressedName, toResourceTypeClass(mediaType))) {
message("storing document " + compressedName + " (" + i + " of " + files.size() + ") " + "...");
document.setContent(isCompressed ? new GZIPInputSource(file) : file);
- ((EXistResource) document).setMimeType(mimeType.getName());
+ ((EXistResource) document).setMediaType(mediaType.getIdentifier());
collection.storeResource(document);
++filesCount;
messageln(" " + Files.size(file) + (isCompressed ? " compressed" : "") + " bytes in "
@@ -1560,7 +1576,7 @@ protected synchronized boolean parseGZip(String fileName) throws XMLDBException,
final long start0 = System.currentTimeMillis();
long bytes = 0;
- MimeType mimeType;
+ @Nullable MediaType mediaType = null;
int i = 0;
for (final Path p : files) {
i++;
@@ -1580,15 +1596,15 @@ protected synchronized boolean parseGZip(String fileName) throws XMLDBException,
break;
}
}
- mimeType = MimeTable.getInstance().getContentTypeFor(localName);
- if (mimeType == null) {
- mimeType = MimeType.BINARY_TYPE;
+ mediaType = mediaTypeResolver.fromFileName(localName);
+ if (mediaType == null) {
+ mediaType = mediaTypeResolver.forUnknown();
}
- try (final Resource document = current.createResource(compressedName, mimeType.getXMLDBType())) {
+ try (final Resource document = current.createResource(compressedName, toResourceTypeClass(mediaType))) {
message("storing document " + compressedName + " (" + i
+ " of " + Files.size(p) + ") ...");
document.setContent(isCompressed ? new GZIPInputSource(p) : p);
- ((EXistResource) document).setMimeType(mimeType.getName());
+ ((EXistResource) document).setMediaType(mediaType.getIdentifier());
current.storeResource(document);
messageln(DONE);
messageln("parsing " + Files.size(p) + (isCompressed ? " compressed" : "") + " bytes took "
@@ -1658,15 +1674,15 @@ protected synchronized boolean parseZip(final Path zipPath) throws XMLDBExceptio
if (!ze.isDirectory()) {
final String localName = pathSteps[pathSteps.length - 1];
final long start = System.currentTimeMillis();
- MimeType mimeType = MimeTable.getInstance().getContentTypeFor(localName);
- if (mimeType == null) {
- mimeType = MimeType.BINARY_TYPE;
+ @Nullable MediaType mediaType = mediaTypeResolver.fromFileName(localName);
+ if (mediaType == null) {
+ mediaType = mediaTypeResolver.forUnknown();
}
- try (final Resource document = base.createResource(localName, mimeType.getXMLDBType())) {
+ try (final Resource document = base.createResource(localName, toResourceTypeClass(mediaType))) {
message("storing Zip-entry document " + localName + " (" + (number)
+ " of " + zfile.size() + ") ...");
document.setContent(new ZipEntryInputSource(zfile, ze));
- ((EXistResource) document).setMimeType(mimeType.getName());
+ ((EXistResource) document).setMediaType(mediaType.getIdentifier());
base.storeResource(document);
messageln(DONE);
messageln("parsing " + ze.getSize() + " bytes took "
@@ -1783,19 +1799,17 @@ private void store(final Collection collection, final Path file, final UploadDia
final long fileSize = FileUtils.sizeQuietly(file);
upload.setCurrentSize(fileSize);
- MimeType mimeType = MimeTable.getInstance().getContentTypeFor(FileUtils.fileName(file));
+ MediaType mediaType = mediaTypeResolver.fromFileName(FileUtils.fileName(file));
// unknown mime type, here prefered is to do nothing
- if (mimeType == null) {
- upload.showMessage(file.toAbsolutePath() +
- " - unknown suffix. No matching mime-type found in : " +
- MimeTable.getInstance().getSrc());
+ if (mediaType == null) {
+ upload.showMessage(file.toAbsolutePath() + " - unknown suffix. No matching mime-type found");
// if some one prefers to store it as binary by default, but dangerous
- mimeType = MimeType.BINARY_TYPE;
+ mediaType = mediaTypeResolver.forUnknown();
}
- try (final Resource res = collection.createResource(filenameUri.toString(), mimeType.getXMLDBType())) {
- ((EXistResource) res).setMimeType(mimeType.getName());
+ try (final Resource res = collection.createResource(filenameUri.toString(), toResourceTypeClass(mediaType))) {
+ ((EXistResource) res).setMediaType(mediaType.getIdentifier());
res.setContent(file);
collection.storeResource(res);
++filesCount;
@@ -2108,7 +2122,10 @@ public boolean run() throws Exception {
final Optional home = ConfigurationHelper.getExistHome();
// get default configuration filename from the driver class and set it in properties
- applyDefaultConfig(home);
+ final Optional configFile = applyDefaultConfig(home);
+
+ @Nullable final Path applicationConfigDir = configFile.map(Path::getParent).filter(Files::exists).orElse(null);
+ this.mediaTypeResolver = MediaTypeUtil.newMediaTypeResolver(applicationConfigDir);
properties.putAll(loadClientProperties());
@@ -2191,7 +2208,7 @@ private boolean checkLoginInfos(boolean interactive) {
return false;
}
- private void applyDefaultConfig(Optional home) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
+ private Optional applyDefaultConfig(Optional home) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Optional configFile = ConfigurationHelper.getFromSystemProperty();
if (!configFile.isPresent()) {
final Class> cl = Class.forName(properties.getProperty(DRIVER));
@@ -2201,6 +2218,7 @@ private void applyDefaultConfig(Optional home) throws ClassNotFoundExcepti
}
}
configFile.ifPresent(value -> properties.setProperty(CONFIGURATION, value.toString()));
+ return configFile;
}
final boolean isInteractive() {
diff --git a/exist-core/src/main/java/org/exist/client/MimeTypeFileFilter.java b/exist-core/src/main/java/org/exist/client/MediaTypeFileFilter.java
similarity index 52%
rename from exist-core/src/main/java/org/exist/client/MimeTypeFileFilter.java
rename to exist-core/src/main/java/org/exist/client/MediaTypeFileFilter.java
index 611aa6e537..aacdcd9ef5 100644
--- a/exist-core/src/main/java/org/exist/client/MimeTypeFileFilter.java
+++ b/exist-core/src/main/java/org/exist/client/MediaTypeFileFilter.java
@@ -1,4 +1,28 @@
/*
+ * Elemental
+ * Copyright (C) 2024, Evolved Binary Ltd
+ *
+ * admin@evolvedbinary.com
+ * https://www.evolvedbinary.com | https://www.elemental.xyz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ * The original license header is included below.
+ *
+ * =====================================================================
+ *
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
@@ -22,12 +46,10 @@
package org.exist.client;
import java.io.File;
-import java.util.Iterator;
-import java.util.List;
import javax.swing.filechooser.FileFilter;
-import org.exist.util.MimeTable;
+import xyz.elemental.mediatype.MediaType;
/**
@@ -36,18 +58,16 @@
*
* Java 6 API has a similar FileNameExtensionFilter
*/
-public class MimeTypeFileFilter extends FileFilter {
+public class MediaTypeFileFilter extends FileFilter {
- private String description = null;
- private List extensions = null;
+ private final MediaType mediaType;
- public MimeTypeFileFilter(String mimeType) {
- description = MimeTable.getInstance().getContentType(mimeType).getDescription();
- extensions = MimeTable.getInstance().getAllExtensions(mimeType);
+ public MediaTypeFileFilter(final MediaType mediaType) {
+ this.mediaType = mediaType;
}
@Override
- public boolean accept(File file) {
+ public boolean accept(final File file) {
if(file.isDirectory()){ //permit directories to be viewed
return true;
}
@@ -60,8 +80,9 @@ public boolean accept(File file) {
//check the extension is that of a file as defined in mime-types.xml
final String fileExtension = file.getName().substring(extensionOffset).toLowerCase();
- for(final String extension : extensions) {
- if(fileExtension.equals(extension)) {
+ final String[] extensions = mediaType.getKnownFileExtensions();
+ for (final String extension : extensions) {
+ if (fileExtension.equals(extension)) {
return true;
}
}
@@ -71,15 +92,16 @@ public boolean accept(File file) {
@Override
public String getDescription() {
- final StringBuilder description = new StringBuilder(this.description);
+ final StringBuilder description = new StringBuilder(mediaType.getIdentifier());
description.append(" (");
- for(final Iterator itExtensions = extensions.iterator(); itExtensions.hasNext();) {
- description.append(itExtensions.next());
- if(itExtensions.hasNext()) {
+ final String[] extensions = mediaType.getKnownFileExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ if (i > 0) {
description.append(' ');
}
+ description.append(extensions[i]);
}
description.append(")");
diff --git a/exist-core/src/main/java/org/exist/client/NewResourceDialog.java b/exist-core/src/main/java/org/exist/client/NewResourceDialog.java
index 8adcdadcc4..fc7dc739f2 100644
--- a/exist-core/src/main/java/org/exist/client/NewResourceDialog.java
+++ b/exist-core/src/main/java/org/exist/client/NewResourceDialog.java
@@ -68,6 +68,7 @@
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.BinaryResource;
import org.xmldb.api.modules.XMLResource;
+import xyz.elemental.mediatype.MediaType;
import static org.exist.util.StringUtil.isNullOrEmpty;
@@ -91,9 +92,9 @@ public NewResourceDialog(final InteractiveClient client) {
}
private enum ResourceType {
- XML_DOCUMENT("XML Document", "xml", "application/xml", "xml-resource.tmpl"),
- XQUERY_MAIN("XQuery Main Module", "xqy", "application/xquery", "xquery-resource.tmpl"),
- XQUERY_LIBRARY("XQuery Library Module", "xqm", "application/xquery", "xquery-lib-resource.tmpl");
+ XML_DOCUMENT("XML Document", "xml", MediaType.APPLICATION_XML, "xml-resource.tmpl"),
+ XQUERY_MAIN("XQuery Main Module", "xqy", MediaType.APPLICATION_XQUERY, "xquery-resource.tmpl"),
+ XQUERY_LIBRARY("XQuery Library Module", "xqm", MediaType.APPLICATION_XQUERY, "xquery-lib-resource.tmpl");
private final String label;
private final String fileExtension;
@@ -315,7 +316,7 @@ private void createResource(final ResourceType resourceType, final String filena
try (final Collection collection = client.current; final Resource resource = collection.createResource(resName, resType)) {
resource.setContent(resourceContent);
- ((EXistResource) resource).setMimeType(resourceType.getMimeType());
+ ((EXistResource) resource).setMediaType(resourceType.getMimeType());
collection.storeResource(resource);
}
client.reloadCollection();
@@ -323,4 +324,4 @@ private void createResource(final ResourceType resourceType, final String filena
ClientFrame.showErrorMessage(xmldbe.getMessage(), xmldbe);
}
}
-}
\ No newline at end of file
+}
diff --git a/exist-core/src/main/java/org/exist/client/QueryDialog.java b/exist-core/src/main/java/org/exist/client/QueryDialog.java
index 291cc435b7..1253ac6eaf 100644
--- a/exist-core/src/main/java/org/exist/client/QueryDialog.java
+++ b/exist-core/src/main/java/org/exist/client/QueryDialog.java
@@ -106,6 +106,7 @@
import org.xmldb.api.base.ResourceIterator;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
+import xyz.elemental.mediatype.MediaType;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.xmldb.api.base.ResourceType.XML_RESOURCE;
@@ -441,7 +442,7 @@ private void open() {
chooser.setCurrentDirectory(Paths.get(workDir).toFile());
chooser.setMultiSelectionEnabled(false);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
- chooser.addChoosableFileFilter(new MimeTypeFileFilter("application/xquery"));
+ chooser.addChoosableFileFilter(new MediaTypeFileFilter(client.getMediaTypeResolver().fromString(MediaType.APPLICATION_XQUERY)));
if (chooser.showDialog(this, Messages.getString("QueryDialog.opendialog")) == JFileChooser.APPROVE_OPTION) {
final Path selectedDir = chooser.getCurrentDirectory().toPath();
@@ -477,10 +478,10 @@ private void save(String stringToSave, String fileCategory) {
chooser.setCurrentDirectory(Paths.get(workDir).toFile());
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
if ("result".equals(fileCategory)) {
- chooser.addChoosableFileFilter(new MimeTypeFileFilter("application/xhtml+xml"));
- chooser.addChoosableFileFilter(new MimeTypeFileFilter("application/xml"));
+ chooser.addChoosableFileFilter(new MediaTypeFileFilter(client.getMediaTypeResolver().fromString(MediaType.APPLICATION_XHTML)));
+ chooser.addChoosableFileFilter(new MediaTypeFileFilter(client.getMediaTypeResolver().fromString(MediaType.APPLICATION_XML)));
} else {
- chooser.addChoosableFileFilter(new MimeTypeFileFilter("application/xquery"));
+ chooser.addChoosableFileFilter(new MediaTypeFileFilter(client.getMediaTypeResolver().fromString(MediaType.APPLICATION_XQUERY)));
}
if (chooser.showDialog(this, Messages.getString("QueryDialog.savedialogpre") + " " + fileCategory + " " + Messages.getString("QueryDialog.savedialogpost"))
== JFileChooser.APPROVE_OPTION) {
diff --git a/exist-core/src/main/java/org/exist/collections/Collection.java b/exist-core/src/main/java/org/exist/collections/Collection.java
index 4e4c2b287f..c7bf145fad 100644
--- a/exist-core/src/main/java/org/exist/collections/Collection.java
+++ b/exist-core/src/main/java/org/exist/collections/Collection.java
@@ -66,6 +66,7 @@
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
+import xyz.elemental.mediatype.MediaType;
import javax.annotation.Nullable;
import java.io.IOException;
@@ -664,7 +665,7 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* Since the process is dependent on the collection configuration,
* the collection acquires a write lock during the process.
*
- * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
+ * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
*
* @param transaction The database transaction
* @param broker The database broker
@@ -678,7 +679,10 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* @throws TriggerException in case of trigger error
* @throws EXistException general exception
* @throws SAXException internal SAXException
+ *
+ * @deprecated Use {@link #storeDocument(Txn, DBBroker, XmldbURI, InputSource, MediaType)} instead.
*/
+ @Deprecated
void storeDocument(Txn transaction, DBBroker broker, XmldbURI name, InputSource source, @Nullable MimeType mimeType) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException;
/**
@@ -686,7 +690,29 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* Since the process is dependent on the collection configuration,
* the collection acquires a write lock during the process.
*
- * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
+ * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
+ *
+ * @param transaction The database transaction
+ * @param broker The database broker
+ * @param name The name (without path) of the document
+ * @param source The source of the content for the new document to store
+ * @param mediaType The Internet Media Type of the document to store, or null if unknown.
+ *
+ * @throws PermissionDeniedException if user has not sufficient rights
+ * @throws LockException if broker is locked
+ * @throws IOException in case of I/O errors
+ * @throws TriggerException in case of trigger error
+ * @throws EXistException general exception
+ * @throws SAXException internal SAXException
+ */
+ void storeDocument(Txn transaction, DBBroker broker, XmldbURI name, InputSource source, @Nullable MediaType mediaType) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException;
+
+ /**
+ * Stores a document.
+ * Since the process is dependent on the collection configuration,
+ * the collection acquires a write lock during the process.
+ *
+ * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
*
* @param transaction The database transaction
* @param broker The database broker
@@ -706,7 +732,10 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* @throws TriggerException in case of trigger error
* @throws EXistException general exception
* @throws SAXException internal SAXException
+ *
+ * @deprecated Use {@link #storeDocument(Txn, DBBroker, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader)} instead.
*/
+ @Deprecated
void storeDocument(Txn transaction, DBBroker broker, XmldbURI name, InputSource source, @Nullable MimeType mimeType, @Nullable Date createdDate, @Nullable Date lastModifiedDate, @Nullable Permission permission, @Nullable DocumentType documentType, @Nullable XMLReader xmlReader) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException;
/**
@@ -714,7 +743,35 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* Since the process is dependent on the collection configuration,
* the collection acquires a write lock during the process.
*
- * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, Node, MimeType, Collection)}
+ * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
+ *
+ * @param transaction The database transaction
+ * @param broker The database broker
+ * @param name The name (without path) of the document
+ * @param source The source of the content for the new document to store
+ * @param mediaType The Internet Media Type of the document to store, or null if unknown.
+ * If null, application/octet-stream will be used to store a binary document.
+ * @param createdDate The created date to set for the document, or if null the date is set to 'now'
+ * @param lastModifiedDate The lastModified date to set for the document, or if null the date is set to the {@code createdDate}
+ * @param permission A specific permission to set on the document, or null for the default permission
+ * @param documentType A document type declaration, or null if absent or a binary document is being stored
+ * @param xmlReader A custom XML Reader (e.g. a HTML to XHTML converting reader), or null to use the default XML reader or if a binary document is being stored
+ *
+ * @throws PermissionDeniedException if user has not sufficient rights
+ * @throws LockException if broker is locked
+ * @throws IOException in case of I/O errors
+ * @throws TriggerException in case of trigger error
+ * @throws EXistException general exception
+ * @throws SAXException internal SAXException
+ */
+ void storeDocument(Txn transaction, DBBroker broker, XmldbURI name, InputSource source, @Nullable MediaType mediaType, @Nullable Date createdDate, @Nullable Date lastModifiedDate, @Nullable Permission permission, @Nullable DocumentType documentType, @Nullable XMLReader xmlReader) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException;
+
+ /**
+ * Stores a document.
+ * Since the process is dependent on the collection configuration,
+ * the collection acquires a write lock during the process.
+ *
+ * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, Node, MediaType, Collection)}
*
* @param transaction The database transaction
* @param broker The database broker
@@ -728,7 +785,10 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* @throws TriggerException in case of trigger error
* @throws EXistException general exception
* @throws SAXException internal SAXException
+ *
+ * @deprecated Use {@link #storeDocument(Txn, DBBroker, XmldbURI, Node, MediaType)} instead.
*/
+ @Deprecated
void storeDocument(Txn transaction, DBBroker broker, XmldbURI name, Node node, @Nullable MimeType mimeType) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException;
/**
@@ -736,7 +796,29 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* Since the process is dependent on the collection configuration,
* the collection acquires a write lock during the process.
*
- * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, Node, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
+ * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, Node, MediaType, Collection)}
+ *
+ * @param transaction The database transaction
+ * @param broker The database broker
+ * @param name The name (without path) of the document
+ * @param node The DOM Node to store as a new document
+ * @param mediaType The Internet Media Type of the document to store, or null if unknown.
+ *
+ * @throws PermissionDeniedException if user has not sufficient rights
+ * @throws LockException if broker is locked
+ * @throws IOException in case of I/O errors
+ * @throws TriggerException in case of trigger error
+ * @throws EXistException general exception
+ * @throws SAXException internal SAXException
+ */
+ void storeDocument(Txn transaction, DBBroker broker, XmldbURI name, Node node, @Nullable MediaType mediaType) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException;
+
+ /**
+ * Stores a document.
+ * Since the process is dependent on the collection configuration,
+ * the collection acquires a write lock during the process.
+ *
+ * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, Node, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
*
* @param transaction The database transaction
* @param broker The database broker
@@ -756,9 +838,40 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* @throws TriggerException in case of trigger error
* @throws EXistException general exception
* @throws SAXException internal SAXException
+ *
+ * @deprecated Use {@link #storeDocument(Txn, DBBroker, XmldbURI, Node, MediaType, Date, Date, Permission, DocumentType, XMLReader)} instead.
*/
+ @Deprecated
void storeDocument(Txn transaction, DBBroker broker, XmldbURI name, Node node, @Nullable MimeType mimeType, @Nullable Date createdDate, @Nullable Date lastModifiedDate, @Nullable Permission permission, @Nullable DocumentType documentType, @Nullable XMLReader xmlReader) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException;
+ /**
+ * Stores a document.
+ * Since the process is dependent on the collection configuration,
+ * the collection acquires a write lock during the process.
+ *
+ * NOTE: This should only be called from {@link NativeBroker#storeDocument(Txn, XmldbURI, Node, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)}
+ *
+ * @param transaction The database transaction
+ * @param broker The database broker
+ * @param name The name (without path) of the document
+ * @param node The DOM Node to store as a new document
+ * @param mediaType The Internet Media Type of the document to store, or null if unknown.
+ * If null, application/octet-stream will be used to store a binary document.
+ * @param createdDate The created date to set for the document, or if null the date is set to 'now'
+ * @param lastModifiedDate The lastModified date to set for the document, or if null the date is set to the {@code createdDate}
+ * @param permission A specific permission to set on the document, or null for the default permission
+ * @param documentType A document type declaration, or null if absent or a binary document is being stored
+ * @param xmlReader A custom XML Reader (e.g. a HTML to XHTML converting reader), or null to use the default XML reader or if a binary document is being stored
+ *
+ * @throws PermissionDeniedException if user has not sufficient rights
+ * @throws LockException if broker is locked
+ * @throws IOException in case of I/O errors
+ * @throws TriggerException in case of trigger error
+ * @throws EXistException general exception
+ * @throws SAXException internal SAXException
+ */
+ void storeDocument(Txn transaction, DBBroker broker, XmldbURI name, Node node, @Nullable MediaType mediaType, @Nullable Date createdDate, @Nullable Date lastModifiedDate, @Nullable Permission permission, @Nullable DocumentType documentType, @Nullable XMLReader xmlReader) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException;
+
/**
* Validates an XML document and prepares it for further storage.
* Launches prepare and postValidate triggers.
@@ -779,7 +892,7 @@ void removeBinaryResource(Txn transaction, DBBroker broker, DocumentImpl doc)
* @throws EXistException general exception
* @throws SAXException internal SAXException
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
IndexInfo validateXMLResource(Txn transaction, DBBroker broker, XmldbURI name, InputSource source)
@@ -807,7 +920,7 @@ IndexInfo validateXMLResource(Txn transaction, DBBroker broker, XmldbURI name, I
* @throws EXistException general exception
* @throws SAXException internal SAXException
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
IndexInfo validateXMLResource(Txn transaction, DBBroker broker, XmldbURI name, InputSource source, XMLReader reader)
@@ -833,7 +946,7 @@ IndexInfo validateXMLResource(Txn transaction, DBBroker broker, XmldbURI name, I
* @throws EXistException general exception
* @throws SAXException internal SAXException
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
IndexInfo validateXMLResource(Txn transaction, DBBroker broker, XmldbURI name, String data)
@@ -859,7 +972,7 @@ IndexInfo validateXMLResource(Txn transaction, DBBroker broker, XmldbURI name, S
* @throws EXistException general exception
* @throws SAXException internal SAXException
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, Node, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, Node, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
IndexInfo validateXMLResource(Txn transaction, DBBroker broker, XmldbURI name, Node node)
@@ -882,7 +995,7 @@ IndexInfo validateXMLResource(Txn transaction, DBBroker broker, XmldbURI name, N
* @throws EXistException general exception
* @throws SAXException internal SAXException
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
void store(Txn transaction, DBBroker broker, IndexInfo info, InputSource source)
@@ -906,7 +1019,7 @@ void store(Txn transaction, DBBroker broker, IndexInfo info, InputSource source)
* @throws EXistException general exception
* @throws SAXException internal SAXException
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
void store(final Txn transaction, final DBBroker broker, final IndexInfo info, final InputSource source, final XMLReader reader)
@@ -929,7 +1042,7 @@ void store(final Txn transaction, final DBBroker broker, final IndexInfo info, f
* @throws EXistException general exception
* @throws SAXException internal SAXException
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
void store(Txn transaction, DBBroker broker, IndexInfo info, String data)
@@ -952,7 +1065,7 @@ void store(Txn transaction, DBBroker broker, IndexInfo info, String data)
* @throws EXistException general exception
* @throws SAXException internal SAXException
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, Node, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, Node, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
void store(Txn transaction, DBBroker broker, IndexInfo info, Node node)
@@ -972,7 +1085,7 @@ void store(Txn transaction, DBBroker broker, IndexInfo info, Node node)
* @throws IOException in case of I/O errors
* @throws TriggerException in case of trigger error
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
BinaryDocument validateBinaryResource(Txn transaction, DBBroker broker, XmldbURI name)
@@ -990,7 +1103,7 @@ BinaryDocument validateBinaryResource(Txn transaction, DBBroker broker, XmldbURI
* @param broker The database broker
* @param name the name (without path) of the document
* @param is The content for the document
- * @param mimeType The Internet Media Type of the document
+ * @param mediaType The Internet Media Type of the document
* @param size The size in bytes of the document (unused - size is calculated during storage)
* @param created The created timestamp of the document
* @param modified The modified timestamp of the document
@@ -1003,10 +1116,10 @@ BinaryDocument validateBinaryResource(Txn transaction, DBBroker broker, XmldbURI
* @throws TriggerException in case of trigger error
* @throws EXistException general exception*
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
- BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, InputStream is, String mimeType,
+ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, InputStream is, String mediaType,
@Deprecated long size, Date created, Date modified) throws EXistException, PermissionDeniedException, LockException,
TriggerException, IOException;
@@ -1022,7 +1135,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @param broker The database broker
* @param name the name (without path) of the document
* @param is The content for the document
- * @param mimeType The Internet Media Type of the document
+ * @param mediaType The Internet Media Type of the document
* @param size The size in bytes of the document (unused - size is calculated during storage)
* @param created The created timestamp of the document
* @param modified The modified timestamp of the document
@@ -1036,10 +1149,10 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @throws TriggerException in case of trigger error
* @throws EXistException general exception*
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
- BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, InputStream is, String mimeType,
+ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, InputStream is, String mediaType,
@Deprecated long size, Date created, Date modified, @Nullable Permission permission) throws EXistException, PermissionDeniedException, LockException,
TriggerException, IOException;
@@ -1055,7 +1168,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @param broker The database broker
* @param name the name (without path) of the document
* @param data The content for the document
- * @param mimeType The Internet Media Type of the document
+ * @param mediaType The Internet Media Type of the document
*
* @return The stored Binary Document object
*
@@ -1068,7 +1181,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @deprecated Use {@link #addBinaryResource(Txn, DBBroker, XmldbURI, InputStream, String, long)}
*/
@Deprecated
- BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, byte[] data, String mimeType)
+ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, byte[] data, String mediaType)
throws EXistException, PermissionDeniedException, LockException, TriggerException, IOException;
/**
@@ -1083,7 +1196,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @param broker The database broker
* @param name the name (without path) of the document
* @param data The content for the document
- * @param mimeType The Internet Media Type of the document
+ * @param mediaType The Internet Media Type of the document
* @param created The created timestamp of the document
* @param modified The modified timestamp of the document
*
@@ -1098,7 +1211,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @deprecated Use {@link #addBinaryResource(Txn, DBBroker, BinaryDocument, InputStream, String, long, Date, Date)}
*/
@Deprecated
- BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, byte[] data, String mimeType,
+ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, byte[] data, String mediaType,
Date created, Date modified) throws EXistException, PermissionDeniedException, LockException,
TriggerException, IOException;
@@ -1114,7 +1227,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @param broker The database broker
* @param name the name (without path) of the document
* @param is The content for the document
- * @param mimeType The Internet Media Type of the document
+ * @param mediaType The Internet Media Type of the document
* @param size The size in bytes of the document (unused - size is calculated during storage)
*
* @return The stored Binary Document object
@@ -1129,7 +1242,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
*/
@Deprecated
BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name, InputStream is,
- String mimeType, @Deprecated long size) throws EXistException, PermissionDeniedException, LockException,
+ String mediaType, @Deprecated long size) throws EXistException, PermissionDeniedException, LockException,
TriggerException, IOException;
/**
@@ -1144,7 +1257,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @param broker The database broker
* @param blob the binary resource to store the data into
* @param is The content for the document
- * @param mimeType The Internet Media Type of the document
+ * @param mediaType The Internet Media Type of the document
* @param size The size in bytes of the document (unused - size is calculated during storage)
* @param created The created timestamp of the document
* @param modified The modified timestamp of the document
@@ -1157,11 +1270,11 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, XmldbURI name
* @throws TriggerException in case of trigger error
* @throws EXistException general exception
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, BinaryDocument blob, InputStream is,
- String mimeType, @Deprecated long size, Date created, Date modified) throws EXistException, PermissionDeniedException,
+ String mediaType, @Deprecated long size, Date created, Date modified) throws EXistException, PermissionDeniedException,
LockException, TriggerException, IOException;
/**
@@ -1176,7 +1289,7 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, BinaryDocumen
* @param broker The database broker
* @param blob the binary resource to store the data into
* @param is The content for the document
- * @param mimeType The Internet Media Type of the document
+ * @param mediaType The Internet Media Type of the document
* @param size The size in bytes of the document (unused - size is calculated during storage)
* @param created The created timestamp of the document
* @param modified The modified timestamp of the document
@@ -1192,11 +1305,11 @@ BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, BinaryDocumen
* @throws TriggerException in case of trigger error
* @throws EXistException general exception
*
- * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MimeType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
+ * @deprecated Use {@link DBBroker#storeDocument(Txn, XmldbURI, InputSource, MediaType, Date, Date, Permission, DocumentType, XMLReader, Collection)} instead.
*/
@Deprecated
BinaryDocument addBinaryResource(Txn transaction, DBBroker broker, BinaryDocument blob, InputStream is,
- String mimeType, @Deprecated long size, Date created, Date modified, DBBroker.PreserveType preserve)
+ String mediaType, @Deprecated long size, Date created, Date modified, DBBroker.PreserveType preserve)
throws EXistException, PermissionDeniedException, LockException, TriggerException, IOException;
/**
diff --git a/exist-core/src/main/java/org/exist/collections/CollectionConfigurationManager.java b/exist-core/src/main/java/org/exist/collections/CollectionConfigurationManager.java
index c0f6c21a90..c6de4bf4b0 100644
--- a/exist-core/src/main/java/org/exist/collections/CollectionConfigurationManager.java
+++ b/exist-core/src/main/java/org/exist/collections/CollectionConfigurationManager.java
@@ -60,7 +60,6 @@
import org.exist.storage.txn.TransactionManager;
import org.exist.storage.txn.Txn;
import org.exist.util.LockException;
-import org.exist.util.MimeType;
import org.exist.util.StringInputSource;
import org.exist.util.XMLReaderPool;
import org.exist.util.sanity.SanityCheck;
@@ -69,6 +68,7 @@
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
+import xyz.elemental.mediatype.MediaType;
import java.io.IOException;
import java.io.StringReader;
@@ -155,7 +155,8 @@ public void addConfiguration(final Txn txn, final DBBroker broker, final Collect
broker.saveCollection(txn, confCol);
- broker.storeDocument(txn, configurationDocumentName, new StringInputSource(config), MimeType.XML_TYPE, confCol);
+ final MediaType xmlMediaType = broker.getBrokerPool().getMediaTypeService().getMediaTypeResolver().fromString(MediaType.APPLICATION_XML);
+ broker.storeDocument(txn, configurationDocumentName, new StringInputSource(config), xmlMediaType, confCol);
// broker.sync(Sync.MAJOR_SYNC);
} catch (final CollectionConfigurationException e) {
diff --git a/exist-core/src/main/java/org/exist/collections/LockedCollection.java b/exist-core/src/main/java/org/exist/collections/LockedCollection.java
index 758af4957b..6ab9bf34ce 100644
--- a/exist-core/src/main/java/org/exist/collections/LockedCollection.java
+++ b/exist-core/src/main/java/org/exist/collections/LockedCollection.java
@@ -66,6 +66,7 @@
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
+import xyz.elemental.mediatype.MediaType;
import javax.annotation.Nullable;
import java.io.IOException;
@@ -386,21 +387,41 @@ public void storeDocument(final Txn transaction, final DBBroker broker, final Xm
broker.storeDocument(transaction, name, source, mimeType, collection);
}
+ @Override
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable final MediaType mediaType) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException {
+ broker.storeDocument(transaction, name, source, mediaType, collection);
+ }
+
@Override
public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable final MimeType mimeType, @Nullable final Date createdDate, @Nullable final Date lastModifiedDate, @Nullable final Permission permission, @Nullable final DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException {
collection.storeDocument(transaction, broker, name, source, mimeType, createdDate, lastModifiedDate, permission, documentType, xmlReader);
}
+ @Override
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable final MediaType mediaType, @Nullable final Date createdDate, @Nullable final Date lastModifiedDate, @Nullable final Permission permission, @Nullable final DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException {
+ collection.storeDocument(transaction, broker, name, source, mediaType, createdDate, lastModifiedDate, permission, documentType, xmlReader);
+ }
+
@Override
public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable final MimeType mimeType) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException {
broker.storeDocument(transaction, name, node, mimeType, collection);
}
+ @Override
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable final MediaType mediaType) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException {
+ broker.storeDocument(transaction, name, node, mediaType, collection);
+ }
+
@Override
public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable final MimeType mimeType, @Nullable final Date createdDate, @Nullable final Date lastModifiedDate, @Nullable final Permission permission, @Nullable final DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException {
collection.storeDocument(transaction, broker, name, node, mimeType, createdDate, lastModifiedDate, permission, documentType, xmlReader);
}
+ @Override
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable final MediaType mediaType, @Nullable final Date createdDate, @Nullable final Date lastModifiedDate, @Nullable final Permission permission, @Nullable final DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException {
+ collection.storeDocument(transaction, broker, name, node, mediaType, createdDate, lastModifiedDate, permission, documentType, xmlReader);
+ }
+
@Deprecated
@Override
public IndexInfo validateXMLResource(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source) throws EXistException, PermissionDeniedException, TriggerException, SAXException, LockException, IOException {
diff --git a/exist-core/src/main/java/org/exist/collections/MutableCollection.java b/exist-core/src/main/java/org/exist/collections/MutableCollection.java
index 81b51376a9..03eb981dc0 100644
--- a/exist-core/src/main/java/org/exist/collections/MutableCollection.java
+++ b/exist-core/src/main/java/org/exist/collections/MutableCollection.java
@@ -92,6 +92,8 @@
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.StorageType;
import javax.annotation.Nullable;
@@ -1124,17 +1126,27 @@ public void removeBinaryResource(final Txn transaction, final DBBroker broker, f
}
@Override
- public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable MimeType mimeType) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable final MimeType mimeType) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
storeDocument(transaction, broker, name, source, mimeType, null, null, null, null, null);
}
@Override
- public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable MimeType mimeType, final @Nullable Date createdDate, final @Nullable Date lastModifiedDate, final @Nullable Permission permission, final @Nullable DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
- if (mimeType == null) {
- mimeType = MimeType.BINARY_TYPE;
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable final MediaType mediaType) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ storeDocument(transaction, broker, name, source, mediaType, null, null, null, null, null);
+ }
+
+ @Override
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable final MimeType mimeType, final @Nullable Date createdDate, final @Nullable Date lastModifiedDate, final @Nullable Permission permission, final @Nullable DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ storeDocument(transaction, broker, name, source, mimeType.toMediaType(), createdDate, lastModifiedDate, permission, documentType, xmlReader);
+ }
+
+ @Override
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final InputSource source, @Nullable MediaType mediaType, final @Nullable Date createdDate, final @Nullable Date lastModifiedDate, final @Nullable Permission permission, final @Nullable DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ if (mediaType == null) {
+ mediaType = broker.getBrokerPool().getMediaTypeService().getMediaTypeResolver().forUnknown();
}
- if (mimeType.isXMLType()) {
+ if (mediaType.getStorageType() == StorageType.XML) {
// Store XML Document
final BiConsumer2E validatorFn = (xmlReader1, validateIndexInfo) -> {
@@ -1157,7 +1169,7 @@ public void storeDocument(final Txn transaction, final DBBroker broker, final Xm
}
};
- storeXmlDocument(transaction, broker, name, mimeType, createdDate, lastModifiedDate, permission, documentType, xmlReader, validatorFn, parserFn);
+ storeXmlDocument(transaction, broker, name, mediaType, createdDate, lastModifiedDate, permission, documentType, xmlReader, validatorFn, parserFn);
} else {
// Store Binary Document
@@ -1165,23 +1177,33 @@ public void storeDocument(final Txn transaction, final DBBroker broker, final Xm
if (is == null) {
throw new IOException("storeDocument received a null InputStream when trying to store a Binary Document");
}
- addBinaryResource(transaction, broker, name, is, mimeType.getName(), -1, createdDate, lastModifiedDate, permission);
+ addBinaryResource(transaction, broker, name, is, mediaType.getIdentifier(), -1, createdDate, lastModifiedDate, permission);
}
}
}
@Override
- public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable MimeType mimeType) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable final MimeType mimeType) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
storeDocument(transaction, broker, name, node, mimeType, null, null, null, null, null);
}
@Override
- public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable MimeType mimeType, final @Nullable Date createdDate, final @Nullable Date lastModifiedDate, final @Nullable Permission permission, final @Nullable DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
- if (mimeType == null) {
- mimeType = MimeType.BINARY_TYPE;
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable final MediaType mediaType) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ storeDocument(transaction, broker, name, node, mediaType, null, null, null, null, null);
+ }
+
+ @Override
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable final MimeType mimeType, final @Nullable Date createdDate, final @Nullable Date lastModifiedDate, final @Nullable Permission permission, final @Nullable DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ storeDocument(transaction, broker, name, node, mimeType.toMediaType(), createdDate, lastModifiedDate, permission, documentType, xmlReader);
+ }
+
+ @Override
+ public void storeDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final Node node, @Nullable MediaType mediaType, final @Nullable Date createdDate, final @Nullable Date lastModifiedDate, final @Nullable Permission permission, final @Nullable DocumentType documentType, @Nullable final XMLReader xmlReader) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ if (mediaType == null) {
+ mediaType = broker.getBrokerPool().getMediaTypeService().getMediaTypeResolver().forUnknown();
}
- if (mimeType.isXMLType()) {
+ if (mediaType.getStorageType() == StorageType.XML) {
// Store XML Document
final BiConsumer2E validatorFn = (xmlReader1, validateIndexInfo) -> {
validateIndexInfo.setReader(xmlReader1, null);
@@ -1194,14 +1216,14 @@ public void storeDocument(final Txn transaction, final DBBroker broker, final Xm
storeIndexInfo.getDOMStreamer().serialize(node, true);
};
- storeXmlDocument(transaction, broker, name, mimeType, createdDate, lastModifiedDate, permission, documentType, xmlReader, validatorFn, parserFn);
+ storeXmlDocument(transaction, broker, name, mediaType, createdDate, lastModifiedDate, permission, documentType, xmlReader, validatorFn, parserFn);
} else {
throw new EXistException("Cannot store DOM Node as a Binary Document to URI: " + getURI().append(name));
}
}
- private void storeXmlDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final MimeType mimeType, final @Nullable Date createdDate, final @Nullable Date lastModifiedDate, final @Nullable Permission permission, final @Nullable DocumentType documentType, @Nullable final XMLReader xmlReader, final BiConsumer2E validatorFn, final BiConsumer2E parserFn) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
+ private void storeXmlDocument(final Txn transaction, final DBBroker broker, final XmldbURI name, final MediaType mediaType, final @Nullable Date createdDate, final @Nullable Date lastModifiedDate, final @Nullable Permission permission, final @Nullable DocumentType documentType, @Nullable final XMLReader xmlReader, final BiConsumer2E validatorFn, final BiConsumer2E parserFn) throws EXistException, PermissionDeniedException, SAXException, LockException, IOException {
final CollectionConfiguration colconf = getConfiguration(broker);
// borrow a default XML Reader if needed
@@ -1220,7 +1242,7 @@ private void storeXmlDocument(final Txn transaction, final DBBroker broker, fina
// Phase 2 of 3 - Set the metadata for the document
final DocumentImpl document = indexInfo.getDocument();
- document.setMimeType(mimeType.getName());
+ document.setMediaType(mediaType.getIdentifier());
if (createdDate != null) {
document.setCreated(createdDate.getTime());
if (lastModifiedDate == null) {
@@ -1832,7 +1854,7 @@ public BinaryDocument addBinaryResource(final Txn transaction, final DBBroker br
}
private BinaryDocument addBinaryResource(final Database db, final Txn transaction, final DBBroker broker,
- final BinaryDocument blob, final InputStream is, final String mimeType, @Deprecated final long size, final Date created,
+ final BinaryDocument blob, final InputStream is, final String mediaType, @Deprecated final long size, final Date created,
final Date modified, @Nullable final Permission permission, final DBBroker.PreserveType preserve, final DocumentImpl oldDoc,
final ManagedCollectionLock collectionLock) throws EXistException, PermissionDeniedException, LockException, TriggerException, IOException {
@@ -1846,7 +1868,7 @@ private BinaryDocument addBinaryResource(final Database db, final Txn transactio
if (!broker.preserveOnCopy(preserve)) {
blob.copyOf(broker, blob, oldDoc);
}
- blob.setMimeType(mimeType == null ? MimeType.BINARY_TYPE.getName() : mimeType);
+ blob.setMediaType(mediaType != null ? mediaType : MediaType.APPLICATION_OCTET_STREAM);
if (created != null) {
blob.setCreated(created.getTime());
}
diff --git a/exist-core/src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java b/exist-core/src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java
index 66b826441f..5c7d909028 100644
--- a/exist-core/src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java
+++ b/exist-core/src/main/java/org/exist/collections/triggers/XQueryStartupTrigger.java
@@ -67,6 +67,7 @@
import org.exist.xquery.XQuery;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.value.Sequence;
+import xyz.elemental.mediatype.MediaType;
import static org.exist.util.StringUtil.endsWith;
import static org.exist.util.StringUtil.substringBeforeLast;
@@ -104,7 +105,7 @@ public class XQueryStartupTrigger implements StartupTrigger {
private static final String XQUERY = "xquery";
private static final String AUTOSTART_COLLECTION = "/db/system/autostart";
private static final String[] XQUERY_EXTENSIONS = {".xq", ".xquery", ".xqy"};
- private static final String REQUIRED_MIMETYPE = "application/xquery";
+ private static final String REQUIRED_MIMETYPE = MediaType.APPLICATION_XQUERY;
@Override
public void execute(DBBroker broker, final Txn transaction, Map> params) {
@@ -208,7 +209,7 @@ private boolean isPermissionsOK(final DocumentImpl document) {
return (perms.getOwner().hasDbaRole()
&& perms.getGroup().getName().equals(SecurityManager.DBA_GROUP)
&& perms.getMode() == Permission.DEFAULT_SYSTEM_SECURITY_COLLECTION_PERM
- && document.getMimeType().equals(REQUIRED_MIMETYPE));
+ && document.getMediaType().equals(REQUIRED_MIMETYPE));
}
diff --git a/exist-core/src/main/java/org/exist/config/Configurator.java b/exist-core/src/main/java/org/exist/config/Configurator.java
index 56477b5d33..ada04750a9 100644
--- a/exist-core/src/main/java/org/exist/config/Configurator.java
+++ b/exist-core/src/main/java/org/exist/config/Configurator.java
@@ -93,7 +93,6 @@
import org.exist.storage.txn.Txn;
import org.exist.util.ExistSAXParserFactory;
import org.exist.util.LockException;
-import org.exist.util.MimeType;
import com.evolvedbinary.j8fu.function.ConsumerE;
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
import org.exist.util.StringInputSource;
@@ -105,6 +104,7 @@
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
+import xyz.elemental.mediatype.MediaType;
import static java.lang.invoke.MethodType.methodType;
import static javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING;
@@ -1334,7 +1334,8 @@ public static DocumentImpl save(final Configurable instance, final DBBroker brok
systemResourcePermission.setGroup(systemSubject.getDefaultGroup());
systemResourcePermission.setMode(Permission.DEFAULT_SYSTEM_RESOURCE_PERM);
- broker.storeDocument(txn, uri, new StringInputSource(data), MimeType.XML_TYPE, null, null, systemResourcePermission, null, null, collection);
+ final MediaType xmlMediaType = broker.getBrokerPool().getMediaTypeService().getMediaTypeResolver().fromString(MediaType.APPLICATION_XML);
+ broker.storeDocument(txn, uri, new StringInputSource(data), xmlMediaType, null, null, systemResourcePermission, null, null, collection);
broker.saveCollection(txn, collection);
if (!txnInProgress) {
diff --git a/exist-core/src/main/java/org/exist/dom/persistent/BinaryDocument.java b/exist-core/src/main/java/org/exist/dom/persistent/BinaryDocument.java
index be14a09b74..36583072a0 100644
--- a/exist-core/src/main/java/org/exist/dom/persistent/BinaryDocument.java
+++ b/exist-core/src/main/java/org/exist/dom/persistent/BinaryDocument.java
@@ -205,7 +205,7 @@ public void write(final VariableByteOutput ostream) throws IOException {
// document attributes
ostream.writeLong(created);
ostream.writeLong(lastModified);
- ostream.writeInt(pool.getSymbols().getMimeTypeId(mimeType));
+ ostream.writeInt(pool.getSymbols().getMimeTypeId(mediaType));
ostream.writeInt(pageCount);
ostream.writeInt(userLock);
if (docType != null) {
diff --git a/exist-core/src/main/java/org/exist/dom/persistent/DocumentImpl.java b/exist-core/src/main/java/org/exist/dom/persistent/DocumentImpl.java
index b0a8f0405f..e5a0f919b8 100644
--- a/exist-core/src/main/java/org/exist/dom/persistent/DocumentImpl.java
+++ b/exist-core/src/main/java/org/exist/dom/persistent/DocumentImpl.java
@@ -63,7 +63,6 @@
import org.exist.storage.lock.EnsureContainerLocked;
import org.exist.storage.lock.EnsureLocked;
import org.exist.storage.txn.Txn;
-import org.exist.util.MimeType;
import org.exist.util.XMLString;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.Constants;
@@ -71,6 +70,7 @@
import org.exist.xquery.NameTest;
import org.exist.xquery.value.Type;
import org.w3c.dom.*;
+import xyz.elemental.mediatype.MediaType;
import javax.annotation.Nullable;
import javax.xml.XMLConstants;
@@ -145,7 +145,7 @@ public class DocumentImpl extends NodeImpl implements Resource, Do
/**
* The mimeType of the document
*/
- protected String mimeType = MimeType.XML_TYPE.getName();
+ protected String mediaType = MediaType.APPLICATION_XML;
/**
* The creation time of this document
@@ -272,7 +272,7 @@ public DocumentImpl(final Expression expression, final int docId, final Document
* @param childAddress the addresses of the child nodes
* @param created the created time of the document
* @param lastModified the last modified time of the document, or null to use the {@code created} time
- * @param mimeType the media type of the document, or null for application/xml
+ * @param mediaType the media type of the document, or null for application/xml
* @param docType the document type, or null
*
* @deprecated Use {@link DocumentImpl(BrokerPool, Collection, int, XmldbURI, Permission, int, long[], long, Long, String, XMLDeclarationImpl, DocumentType)}
@@ -281,9 +281,9 @@ public DocumentImpl(final Expression expression, final int docId, final Document
public DocumentImpl(final BrokerPool pool, @Nullable final Collection collection,
final int docId, final XmldbURI fileURI, final Permission permissions,
final int children, @Nullable final long[] childAddress,
- final long created, @Nullable final Long lastModified, @Nullable final String mimeType,
+ final long created, @Nullable final Long lastModified, @Nullable final String mediaType,
@Nullable final DocumentType docType) {
- this(null, pool, collection, docId, fileURI, permissions, children, childAddress, created, lastModified, mimeType, null, docType);
+ this(null, pool, collection, docId, fileURI, permissions, children, childAddress, created, lastModified, mediaType, null, docType);
}
/**
@@ -298,16 +298,16 @@ public DocumentImpl(final BrokerPool pool, @Nullable final Collection collection
* @param childAddress the addresses of the child nodes
* @param created the created time of the document
* @param lastModified the last modified time of the document, or null to use the {@code created} time
- * @param mimeType the media type of the document, or null for application/xml
+ * @param mediaType the media type of the document, or null for application/xml
* @param xmlDecl the XML Declaration, or null
* @param docType the document type, or null
*/
public DocumentImpl(final BrokerPool pool, @Nullable final Collection collection,
final int docId, final XmldbURI fileURI, final Permission permissions,
final int children, @Nullable final long[] childAddress,
- final long created, @Nullable final Long lastModified, @Nullable final String mimeType,
+ final long created, @Nullable final Long lastModified, @Nullable final String mediaType,
@Nullable final XMLDeclarationImpl xmlDecl, @Nullable final DocumentType docType) {
- this(null, pool, collection, docId, fileURI, permissions, children, childAddress, created, lastModified, mimeType, xmlDecl, docType);
+ this(null, pool, collection, docId, fileURI, permissions, children, childAddress, created, lastModified, mediaType, xmlDecl, docType);
}
/**
@@ -323,7 +323,7 @@ public DocumentImpl(final BrokerPool pool, @Nullable final Collection collection
* @param childAddress the addresses of the child nodes
* @param created the created time of the document
* @param lastModified the last modified time of the document, or null to use the {@code created} time
- * @param mimeType the media type of the document, or null for application/xml
+ * @param mediaType the media type of the document, or null for application/xml
* @param docType the document type, or null
*
* @deprecated Use {@link DocumentImpl(Expression, BrokerPool, Collection, int ,XmldbURI, Permission, int, long[], long, Long, String, XMLDeclarationImpl, DocumentType)}
@@ -332,9 +332,9 @@ public DocumentImpl(final BrokerPool pool, @Nullable final Collection collection
public DocumentImpl(final Expression expression, final BrokerPool pool, @Nullable final Collection collection,
final int docId, final XmldbURI fileURI, final Permission permissions,
final int children, @Nullable final long[] childAddress,
- final long created, @Nullable final Long lastModified, @Nullable final String mimeType,
+ final long created, @Nullable final Long lastModified, @Nullable final String mediaType,
@Nullable final DocumentType docType) {
- this(expression, pool, collection, docId, fileURI, permissions, children, childAddress, created, lastModified, mimeType, null, docType);
+ this(expression, pool, collection, docId, fileURI, permissions, children, childAddress, created, lastModified, mediaType, null, docType);
}
/**
@@ -350,14 +350,14 @@ public DocumentImpl(final Expression expression, final BrokerPool pool, @Nullabl
* @param childAddress the addresses of the child nodes
* @param created the created time of the document
* @param lastModified the last modified time of the document, or null to use the {@code created} time
- * @param mimeType the media type of the document, or null for application/xml
+ * @param mediaType the media type of the document, or null for application/xml
* @param xmlDecl the XML Declaration, or null
* @param docType the document type, or null
*/
public DocumentImpl(final Expression expression, final BrokerPool pool, @Nullable final Collection collection,
final int docId, final XmldbURI fileURI, final Permission permissions,
final int children, @Nullable final long[] childAddress,
- final long created, @Nullable final Long lastModified, @Nullable final String mimeType,
+ final long created, @Nullable final Long lastModified, @Nullable final String mediaType,
@Nullable final XMLDeclarationImpl xmlDecl, @Nullable final DocumentType docType) {
super(expression);
this.pool = pool;
@@ -372,7 +372,7 @@ public DocumentImpl(final Expression expression, final BrokerPool pool, @Nullabl
this.childAddress = childAddress;
this.created = created;
this.lastModified = lastModified == null ? created : lastModified;
- this.mimeType = mimeType == null ? MimeType.XML_TYPE.getName() : mimeType;
+ this.mediaType = mediaType != null ? mediaType : MediaType.APPLICATION_XML;
this.xmlDecl = xmlDecl;
this.docType = docType;
@@ -489,12 +489,42 @@ public void setLastModified(final long lastModified) {
this.lastModified = lastModified;
}
+ /**
+ * Get the Internet Media Type of the document.
+ *
+ * @return the Internet Media Type of the document.
+ *
+ * @deprecated Use {@link #getMediaType()} instead.
+ */
+ @Deprecated
public String getMimeType() {
- return mimeType;
+ return mediaType;
}
+ /**
+ * Set the Internet Media Type of the document.
+ *
+ * @deprecated Use {@link #setMediaType(String)} instead.
+ */
+ @Deprecated
public void setMimeType(final String mimeType) {
- this.mimeType = mimeType;
+ this.mediaType = mimeType;
+ }
+
+ /**
+ * Get the Internet Media Type of the document.
+ *
+ * @return the Internet Media Type of the document.
+ */
+ public String getMediaType() {
+ return mediaType;
+ }
+
+ /**
+ * Set the Internet Media Type of the document.
+ */
+ public void setMediaType(final String mediaType) {
+ this.mediaType = mediaType;
}
/**
@@ -683,7 +713,7 @@ private void copyOf(final DBBroker broker, @EnsureLocked(mode=READ_LOCK) final D
this.created = other.created;
this.lastModified = other.lastModified;
- this.mimeType = other.mimeType;
+ this.mediaType = other.mediaType;
this.docType = other.docType;
final long timestamp = System.currentTimeMillis();
@@ -888,7 +918,7 @@ public void write(final VariableByteOutput ostream) throws IOException {
void writeDocumentAttributes(final SymbolTable symbolTable, final VariableByteOutput ostream) throws IOException {
ostream.writeLong(created);
ostream.writeLong(lastModified);
- ostream.writeInt(symbolTable.getMimeTypeId(mimeType));
+ ostream.writeInt(symbolTable.getMimeTypeId(mediaType));
ostream.writeInt(pageCount);
ostream.writeInt(userLock);
if (xmlDecl != null) {
diff --git a/exist-core/src/main/java/org/exist/dom/persistent/DocumentMetadata.java b/exist-core/src/main/java/org/exist/dom/persistent/DocumentMetadata.java
index 38fbe79c54..6b6252f1b3 100644
--- a/exist-core/src/main/java/org/exist/dom/persistent/DocumentMetadata.java
+++ b/exist-core/src/main/java/org/exist/dom/persistent/DocumentMetadata.java
@@ -95,12 +95,12 @@ public void setLastModified(final long lastModified) {
@Deprecated
public String getMimeType() {
- return doc.getMimeType();
+ return doc.getMediaType();
}
@Deprecated
public void setMimeType(final String mimeType) {
- doc.setMimeType(mimeType);
+ doc.setMediaType(mimeType);
}
@Deprecated
@@ -133,7 +133,7 @@ public void read(final SymbolTable symbolTable, final VariableByteInput istream)
final long created = istream.readLong();
final long lastModified = istream.readLong();
final int mimeTypeSymbolsIndex = istream.readInt();
- final String mimeType = symbolTable.getMimeType(mimeTypeSymbolsIndex);
+ final String mediaType = symbolTable.getMimeType(mimeTypeSymbolsIndex);
final int pageCount = istream.readInt();
final int userLock = istream.readInt();
final DocumentTypeImpl docType;
@@ -151,7 +151,7 @@ public void read(final SymbolTable symbolTable, final VariableByteInput istream)
doc.setCreated(created);
doc.setLastModified(lastModified);
- doc.setMimeType(mimeType);
+ doc.setMediaType(mediaType);
doc.setPageCount(pageCount);
doc.setUserLock(userLock);
doc.setDocType(docType);
diff --git a/exist-core/src/main/java/org/exist/http/RESTServer.java b/exist-core/src/main/java/org/exist/http/RESTServer.java
index 84430b4531..8254b7743d 100644
--- a/exist-core/src/main/java/org/exist/http/RESTServer.java
+++ b/exist-core/src/main/java/org/exist/http/RESTServer.java
@@ -108,6 +108,8 @@
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.XMLFilterImpl;
+import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeResolver;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -147,7 +149,7 @@ public class RESTServer {
static {
defaultProperties.setProperty(OutputKeys.INDENT, "yes");
- defaultProperties.setProperty(OutputKeys.MEDIA_TYPE, MimeType.XML_TYPE.getName());
+ defaultProperties.setProperty(OutputKeys.MEDIA_TYPE, MediaType.APPLICATION_XML);
defaultProperties.setProperty(EXistOutputKeys.EXPAND_XINCLUDES, "yes");
defaultProperties.setProperty(EXistOutputKeys.HIGHLIGHT_MATCHES, "elements");
defaultProperties.setProperty(EXistOutputKeys.PROCESS_XSL_PI, "yes");
@@ -158,8 +160,7 @@ public class RESTServer {
defaultOutputKeysProperties.setProperty(EXistOutputKeys.OMIT_ORIGINAL_XML_DECLARATION, "no");
defaultOutputKeysProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
defaultOutputKeysProperties.setProperty(OutputKeys.INDENT, "yes");
- defaultOutputKeysProperties.setProperty(OutputKeys.MEDIA_TYPE,
- MimeType.XML_TYPE.getName());
+ defaultOutputKeysProperties.setProperty(OutputKeys.MEDIA_TYPE, MediaType.APPLICATION_XML);
}
private final static String QUERY_ERROR_HEAD = "" + ""
+ "Query Error" + "