> parseFn) {
+ try {
+ assert (!configSources.isLinear());
+
+ final JAXBContext context;
+ final Unmarshaller unmarshaller;
+ try {
+ context = JAXBContext.newInstance(configClass);
+ unmarshaller = context.createUnmarshaller();
+ } catch (final JAXBException e) {
+ LOG.error("Unable to instantiate JAXB Unmarshaller: {}", e.getMessage(), e);
+ return List.EMPTY;
+ }
+
+ final LinearList results = new LinearList<>();
+ for (final MediaTypeConfigSource configSource : configSources) {
+ if (configSource.path != null && !Files.exists(configSource.path)) {
+ LOG.warn("Config path {} does not exist, skipping...", configSource.path);
+ continue;
+ }
+
+ try {
+ final C config;
+ if (configSource.path != null) {
+ config = (C) unmarshaller.unmarshal(configSource.path.toUri().toURL());
+ } else {
+ config = (C) unmarshaller.unmarshal(configSource.is);
+ }
+ if (config == null) {
+ LOG.error("No config found in {} skipping...", configSource.location);
+ continue;
+ }
+
+ parseFn.accept(configSource.location, config, results);
+
+ } 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: {}", configSource.location, message, e);
+ }
+ }
+
+ return results.forked();
+
+ } finally {
+ for (final MediaTypeConfigSource configSource : configSources) {
+ if (configSource.is != null) {
+ try {
+ configSource.is.close();
+ } catch (final IOException e) {
+ LOG.warn("Unable to close config file source: {} ", configSource.location, e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Some source of configuration information.
+ *
+ * Either {@link #path} or {@link #is} will be set, but never both.
+ */
+ static class MediaTypeConfigSource {
+ private final String location;
+
+ @Nullable private final Path path;
+ @Nullable private final InputStream is;
+
+ private MediaTypeConfigSource(final Path path) {
+ this.location = path.normalize().toAbsolutePath().toString();
+ this.path = path;
+ this.is = null;
+ }
+
+ private MediaTypeConfigSource(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/MediaTypeImpl.java b/elemental-media-type/elemental-media-type-impl/src/main/java/xyz/elemental/mediatype/impl/MediaTypeImpl.java
index 21ac682c9d..ea8d302372 100644
--- 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
@@ -115,6 +115,7 @@ private Builder(final String identifier, final StorageType storageType) {
*
* @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
*/
static Builder forMediaType(final String identifier, final StorageType storageType) {
return new Builder(identifier, 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
index cc1786a2b3..76f2ae384e 100644
--- 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
@@ -37,30 +37,24 @@
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.MediaTypeConfigUtil.MediaTypeConfigSource;
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;
+import static xyz.elemental.mediatype.impl.MediaTypeConfigUtil.findConfigSources;
+import static xyz.elemental.mediatype.impl.MediaTypeConfigUtil.parseConfigSources;
+
/**
* Maps Media Types to database Storage Types.
* Mappings file search order.
@@ -92,153 +86,61 @@ public class MediaTypeMapper {
private final Function[] matchers;
public MediaTypeMapper(@Nullable final Path... configDirs) {
- final IList mappingsFileSources = getMappingsFileSources(configDirs);
- this.matchers = loadMatchers(mappingsFileSources);
+ final IList mappingsFileSources = findConfigSources(MediaTypeMapper.class, MEDIA_TYPE_MAPPINGS_FILENAME, configDirs);
+ final IList> matchers = parseConfigSources(MediaTypeMappings.class, mappingsFileSources, MediaTypeMapper::mappingsToMatchers);
+ this.matchers = matchers.toArray(Function[]::new);
}
- 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));
+ private static void mappingsToMatchers(final String configLocation, final MediaTypeMappings mediaTypeMappings, final IList> matchers) {
+ if (mediaTypeMappings.getStorage() == null || mediaTypeMappings.getStorage().isEmpty()) {
+ LOG.error("No mappings found in {} skipping...", configLocation);
+ return;
}
- 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();
+ for (final Storage storage : mediaTypeMappings.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;
- 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);
+ default:
+ throw new IllegalArgumentException();
}
- }
-
- 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);
- }
- }
+ matchers.addLast(matcher);
}
}
}
@@ -287,26 +189,4 @@ public StorageType resolveStorageType(final String mediaTypeIdentifier) {
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
index 016a73f8e2..bfcac15c46 100644
--- 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
@@ -62,7 +62,8 @@ public MediaTypeResolver newMediaTypeResolver() {
public MediaTypeResolver newMediaTypeResolver(@Nullable final Path... configDirs) {
final ApplicationMimetypesFileTypeMap mimetypesFileTypeMap = new ApplicationMimetypesFileTypeMap(
configDirs);
+ final MediaTypeAliaser mediaTypeAliaser = new MediaTypeAliaser(configDirs);
final MediaTypeMapper mediaTypeMapper = new MediaTypeMapper(configDirs);
- return new MediaTypeResolverImpl(mimetypesFileTypeMap, mediaTypeMapper);
+ return new MediaTypeResolverImpl(mimetypesFileTypeMap, mediaTypeAliaser, 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
index c03d19a750..87dfef9d54 100644
--- 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
@@ -37,6 +37,7 @@
package xyz.elemental.mediatype.impl;
import com.sun.activation.registries.MimeTypeEntry;
+import io.lacuna.bifurcan.IEntry;
import io.lacuna.bifurcan.IList;
import io.lacuna.bifurcan.LinearMap;
import jakarta.activation.MimetypesFileTypeMap;
@@ -44,6 +45,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeAlias;
import xyz.elemental.mediatype.MediaTypeResolver;
import xyz.elemental.mediatype.StorageType;
@@ -70,15 +72,17 @@ public class MediaTypeResolverImpl implements MediaTypeResolver {
private final io.lacuna.bifurcan.IMap extensionsIndex;
private final io.lacuna.bifurcan.IMap identifiersIndex;
+ private final io.lacuna.bifurcan.IMap aliasIdentifiersIndex;
private final MediaType defaultMediaType;
- public MediaTypeResolverImpl(final ApplicationMimetypesFileTypeMap fileTypeMap, final MediaTypeMapper mediaTypeMapper) {
+ public MediaTypeResolverImpl(final ApplicationMimetypesFileTypeMap fileTypeMap, final MediaTypeAliaser mediaTypeAliaser, 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.aliasIdentifiersIndex = io.lacuna.bifurcan.Map.empty();
this.defaultMediaType = null;
return;
}
@@ -119,10 +123,28 @@ public MediaTypeResolverImpl(final ApplicationMimetypesFileTypeMap fileTypeMap,
this.extensionsIndex = mutExtensionsIndex.mapValues((k, v) -> v.build()).forked();
this.identifiersIndex = mutIdentifiersIndex.mapValues((k, v) -> v.build()).forked();
-
assert(!extensionsIndex.isLinear());
assert(!identifiersIndex.isLinear());
+ final LinearMap mutAliasIdentifiersIndex = new LinearMap<>((int) mediaTypeAliaser.aliases.size());
+ for (final IEntry alias : mediaTypeAliaser.aliases.entries()) {
+ final String aliasIdentifier = alias.key();
+ final String aliasTo = alias.value();
+ @Nullable final MediaType aliasTarget = identifiersIndex.get(aliasTo, null);
+ if (aliasTarget == null) {
+ LOG.warn("No Media Type definition found for alias: {}. Alias will be ignored!", aliasIdentifier);
+ continue;
+ }
+
+ final MediaTypeAliasImpl.Builder mediaTypeAliasBuilder = MediaTypeAliasImpl.builder(aliasIdentifier)
+ .of(aliasTarget);
+
+ mutAliasIdentifiersIndex.put(aliasIdentifier, mediaTypeAliasBuilder);
+ }
+
+ this.aliasIdentifiersIndex = mutAliasIdentifiersIndex.mapValues((k, v) -> v.build()).forked();
+ assert(!aliasIdentifiersIndex.isLinear());
+
this.defaultMediaType = identifiersIndex.get(APPLICATION_OCTET_STREAM)
.orElseGet(() -> MediaTypeImpl.Builder.forMediaType(APPLICATION_OCTET_STREAM, StorageType.BINARY).build());
}
@@ -167,12 +189,21 @@ public MediaTypeResolverImpl(final ApplicationMimetypesFileTypeMap fileTypeMap,
}
@Override
- public @Nullable MediaType fromString(@Nullable final String mediaType) {
+ public @Nullable MediaType fromString(@Nullable String mediaType) {
if (mediaType == null) {
return null;
}
- return identifiersIndex.get(mediaType.toLowerCase(), null);
+ mediaType = mediaType.toLowerCase();
+
+ // 1. try and resolve any alias first
+ @Nullable final MediaType aliasTarget = aliasIdentifiersIndex.get(mediaType, null);
+ if (aliasTarget != null) {
+ return aliasTarget;
+ }
+
+ // 2. if it is not an alias, then resolve the media type itself
+ return identifiersIndex.get(mediaType, null);
}
@Override
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-configuration.xjb
similarity index 84%
rename from elemental-media-type/elemental-media-type-impl/src/main/xjb/media-type-mappings.xjb
rename to elemental-media-type/elemental-media-type-impl/src/main/xjb/media-type-configuration.xjb
index 7df9688282..429902145f 100644
--- 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-configuration.xjb
@@ -38,9 +38,18 @@
-->
+
+
+
+
+
\ No newline at end of file
diff --git a/elemental-media-type/elemental-media-type-impl/src/main/xsd/media-type-aliases.xsd b/elemental-media-type/elemental-media-type-impl/src/main/xsd/media-type-aliases.xsd
new file mode 100644
index 0000000000..0c0815838b
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/main/xsd/media-type-aliases.xsd
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+ Defined Media Types as aliases to other Media Types.
+
+
+
+
+
+
+
+
+
+
+
+ Each Media Type alias should only appear once
+
+
+
+
+
+
+
+
+ Creates a Media Type Alias
+
+
+
+
+
+ Optional documentation describing the purpose of the alias
+
+
+
+
+
+ The Media Type alias identifier for the Media Type
+
+
+
+
+ The identifier of the Media Type that is being aliased
+
+
+
+
+
+
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
index f90a90d06e..0578507750 100644
--- 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
@@ -39,6 +39,7 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import xyz.elemental.mediatype.MediaType;
+import xyz.elemental.mediatype.MediaTypeAlias;
import xyz.elemental.mediatype.MediaTypeResolver;
import xyz.elemental.mediatype.StorageType;
@@ -49,28 +50,29 @@
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;
+import static org.junit.jupiter.api.Assertions.*;
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 MediaTypeAliaser MEDIA_TYPE_ALIASER = null;
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 mediaTypeAliases = MediaTypeResolverImplTest.class.getResource("media-type-aliases.xml");
+ assertNotNull(mediaTypeAliases);
@Nullable final URL mediaTypeMappings = MediaTypeResolverImplTest.class.getResource("media-type-mappings.xml");
assertNotNull(mediaTypeMappings);
final Path configDir = Paths.get(mediaTypeMappings.toURI()).getParent();
+ MEDIA_TYPE_ALIASER = new MediaTypeAliaser(configDir);
MEDIA_TYPE_MAPPER = new MediaTypeMapper(configDir);
final ApplicationMimetypesFileTypeMap defaultMimetypesFileTypeMap = new ApplicationMimetypesFileTypeMap((Path[]) null);
- DEFAULT_MEDIA_RESOLVER = new MediaTypeResolverImpl(defaultMimetypesFileTypeMap, MEDIA_TYPE_MAPPER);
+ DEFAULT_MEDIA_RESOLVER = new MediaTypeResolverImpl(defaultMimetypesFileTypeMap, MEDIA_TYPE_ALIASER, MEDIA_TYPE_MAPPER);
APPLICATION_MEDIA_RESOLVER = new MediaTypeResolverFactoryImpl().newMediaTypeResolver(configDir);
}
@@ -485,6 +487,14 @@ public void defaultResolveXmlIdentifier() {
//
+ //
+ @Test
+ public void defaultResolveTextXmlAliasIdentifier() {
+ assertDefaultResolveFromAliasIdentifier("text/xml", MediaType.APPLICATION_XML, new String[] {"xsl", "xml"}, StorageType.XML);
+ }
+ //
+
+
//
@Test
public void applicationResolveDitaExtension() {
@@ -693,6 +703,19 @@ public void applicationResolveXqueryXIdentifier() {
//
+ //
+ @Test
+ public void applicationResolveTextXmlAliasIdentifier() {
+ assertApplicationResolveFromAliasIdentifier("text/xml", MediaType.APPLICATION_XML, new String[] {"fo", "nvdl", "rng", "stx", "xconf", "xml", "xsd", "xsl"}, StorageType.XML);
+ }
+
+ @Test
+ public void applicationResolveApplicationAdamQueryAliasIdentifier() {
+ assertApplicationResolveFromAliasIdentifier("application/adam-query", MediaType.APPLICATION_XQUERY, new String[] {"xq", "xql", "xqm", "xquery", "xqws", "xqy"}, StorageType.BINARY);
+ }
+ //
+
+
/**
* Check that multiple levels of mime.types files
* yield correct lookups via. both
@@ -720,7 +743,7 @@ public void resolveFromCorrectLevel() throws URISyntaxException {
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);
+ final MediaTypeResolverImpl specificMediaTypeResolver = new MediaTypeResolverImpl(mimetypesFileTypeMap, MEDIA_TYPE_ALIASER, 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);
@@ -815,12 +838,41 @@ private void assertDefaultResolveFromIdentifier(final String identifier, final S
private void assertApplicationResolveFromIdentifier(final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
assertNotNull(APPLICATION_MEDIA_RESOLVER);
- assertResolveFromIdentifier(APPLICATION_MEDIA_RESOLVER, identifier, expectedExtensions, expectedStorageType);
+ 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);
+ assertEquals(identifier, mediaType.getIdentifier());
+ assertArrayAnyOrderEquals(expectedExtensions, mediaType.getKnownFileExtensions());
+ assertEquals(expectedStorageType, mediaType.getStorageType());
+ }
+
+ private void assertAllResolveFromAliasIdentifier(final String aliasIdentifier, final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertDefaultResolveFromAliasIdentifier(aliasIdentifier, identifier, expectedExtensions, expectedStorageType);
+ assertApplicationResolveFromAliasIdentifier(aliasIdentifier, identifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertDefaultResolveFromAliasIdentifier(final String aliasIdentifier, final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertNotNull(DEFAULT_MEDIA_RESOLVER);
+ assertResolveFromAliasIdentifier(DEFAULT_MEDIA_RESOLVER, aliasIdentifier, identifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertApplicationResolveFromAliasIdentifier(final String aliasIdentifier, final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ assertNotNull(APPLICATION_MEDIA_RESOLVER);
+ assertResolveFromAliasIdentifier(APPLICATION_MEDIA_RESOLVER, aliasIdentifier, identifier, expectedExtensions, expectedStorageType);
+ }
+
+ private void assertResolveFromAliasIdentifier(final MediaTypeResolver mediaTypeResolver, final String aliasIdentifier, final String identifier, final String[] expectedExtensions, final StorageType expectedStorageType) {
+ final @Nullable MediaType mediaType = mediaTypeResolver.fromString(aliasIdentifier);
+ assertNotNull(mediaType);
+ assertEquals(identifier, mediaType.getIdentifier());
+
+ assertTrue(mediaType instanceof MediaTypeAlias);
+ final MediaTypeAlias mediaTypeAlias = (MediaTypeAlias) mediaType;
+ assertEquals(aliasIdentifier, mediaTypeAlias.getAliasIdentifier());
+
assertArrayAnyOrderEquals(expectedExtensions, mediaType.getKnownFileExtensions());
assertEquals(expectedStorageType, mediaType.getStorageType());
}
diff --git a/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/media-type-aliases.xml b/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/media-type-aliases.xml
new file mode 100644
index 0000000000..df81fd6be2
--- /dev/null
+++ b/elemental-media-type/elemental-media-type-impl/src/test/resources/xyz/elemental/mediatype/impl/media-type-aliases.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+ text/xml is an alias for application/xml as described in IETF RFC 7303
+
+
+
+ A made up alias for testing purposes
+
+
+
\ No newline at end of file
diff --git a/elemental-parent/pom.xml b/elemental-parent/pom.xml
index 6c43c96de3..c19d04b653 100644
--- a/elemental-parent/pom.xml
+++ b/elemental-parent/pom.xml
@@ -121,6 +121,12 @@
3.0.2