Config now uses common media type module instead of FileTypeDetector.

This commit is contained in:
Tomas Langer
2020-01-29 20:31:07 +01:00
committed by Tomas Langer
parent e6fb6a72b2
commit 6c2ab5d326
26 changed files with 64 additions and 350 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,10 +17,10 @@
package io.helidon.config;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.Optional;
import io.helidon.common.media.type.MediaTypes;
import io.helidon.config.spi.AbstractParsableConfigSource;
import io.helidon.config.spi.ConfigParser;
import io.helidon.config.spi.ConfigSource;
@@ -90,7 +90,7 @@ public class ClasspathConfigSource extends AbstractParsableConfigSource<Instant>
}
private Optional<String> probeContentType() {
return Optional.ofNullable(ConfigHelper.detectContentType(Paths.get(resource)));
return MediaTypes.detectType(resource);
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,26 +20,17 @@ import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.nio.CharBuffer;
import java.nio.file.Path;
import java.nio.file.spi.FileTypeDetector;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.concurrent.Flow;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.helidon.config.internal.ConfigFileTypeDetector;
/**
* Common Configuration utilities.
*/
public final class ConfigHelper {
private static final int DEFAULT_BUFFER_CAPACITY = 1024;
private static final Logger LOGGER = Logger.getLogger(ConfigFileTypeDetector.class.getName());
private static final Logger LOGGER = Logger.getLogger(ConfigHelper.class.getName());
private ConfigHelper() {
throw new AssertionError("Instantiation not allowed.");
@@ -137,54 +128,6 @@ public final class ConfigHelper {
};
}
// lazy loading of default and installed file type detectors
private static class FileTypeDetectors {
static final List<FileTypeDetector> INSTALLED_DETECTORS =
loadInstalledDetectors();
// loads all installed file type detectors
private static List<FileTypeDetector> loadInstalledDetectors() {
return AccessController
.doPrivileged(new PrivilegedAction<List<FileTypeDetector>>() {
@Override
public List<FileTypeDetector> run() {
List<FileTypeDetector> list = new LinkedList<>();
ServiceLoader<FileTypeDetector> loader = ServiceLoader
.load(FileTypeDetector.class);
for (FileTypeDetector detector : loader) {
list.add(detector);
}
return list;
}
});
}
}
/**
* Infers the content type contained in the provided {@code Path}.
*
* @param path path to check
* @return string with content type
*/
public static String detectContentType(Path path) {
String result = null;
try {
for (FileTypeDetector detector : FileTypeDetectors.INSTALLED_DETECTORS) {
result = detector.probeContentType(path);
if (result != null) {
break;
}
}
} catch (IOException e) {
LOGGER.log(Level.FINEST,
e,
() -> "Failed to find content type for " + path);
}
return result;
}
/**
* Implementation of {@link ConfigHelper#subscriber(Function)}.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.helidon.common.media.type.MediaTypes;
import io.helidon.config.internal.FileSourceHelper;
import io.helidon.config.spi.AbstractParsableConfigSource;
import io.helidon.config.spi.ConfigParser;
@@ -97,7 +98,7 @@ public class FileConfigSource extends AbstractParsableConfigSource<byte[]> {
}
private Optional<String> probeContentType() {
return Optional.ofNullable(ConfigHelper.detectContentType(filePath));
return MediaTypes.detectType(filePath);
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,18 +20,16 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.helidon.common.media.type.MediaTypes;
import io.helidon.config.internal.ConfigUtils;
import io.helidon.config.spi.AbstractParsableConfigSource;
import io.helidon.config.spi.ConfigParser;
@@ -162,25 +160,8 @@ public class UrlConfigSource extends AbstractParsableConfigSource<Instant> {
return mediaType;
}
private String probeContentType() throws URISyntaxException {
URI uri = url.toURI();
Path path;
switch (uri.getScheme()) {
case "jar":
String relativePath = uri.getSchemeSpecificPart();
int idx = relativePath.indexOf("!");
if (idx > 0 && idx < relativePath.length()) {
relativePath = relativePath.substring(idx + 1);
}
path = Paths.get(relativePath);
break;
case "file":
path = Paths.get(uri);
break;
default:
path = Paths.get(url.getPath());
}
return ConfigHelper.detectContentType(path);
private String probeContentType() {
return MediaTypes.detectType(url).orElse(null);
}
@Override

View File

@@ -1,37 +0,0 @@
/*
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.helidon.config.internal;
import java.nio.file.Path;
import java.nio.file.spi.FileTypeDetector;
/**
* Custom implementation of Java {@link FileTypeDetector} to support core format (Java Properties).
*/
public class ConfigFileTypeDetector extends FileTypeDetector {
@Override
public String probeContentType(Path path) {
String resourceUri = path.toString();
if (resourceUri.indexOf('.') != -1) {
String fileExt = resourceUri.substring(resourceUri.lastIndexOf('.'));
if (fileExt.equals(".properties")) {
return PropertiesConfigParser.MEDIA_TYPE_TEXT_JAVA_PROPERTIES;
}
}
return null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ module io.helidon.config {
requires transitive io.helidon.common;
requires transitive io.helidon.common.reactive;
requires io.helidon.common.serviceloader;
requires io.helidon.common.media.type;
requires transitive io.helidon.common.media.type;
requires transitive microprofile.config.api;
exports io.helidon.config;
@@ -46,10 +46,7 @@ module io.helidon.config {
uses org.eclipse.microprofile.config.spi.ConfigSourceProvider;
uses org.eclipse.microprofile.config.spi.Converter;
uses java.nio.file.spi.FileTypeDetector;
provides io.helidon.config.spi.ConfigParser with io.helidon.config.internal.PropertiesConfigParser;
provides java.nio.file.spi.FileTypeDetector with io.helidon.config.internal.ConfigFileTypeDetector;
provides org.eclipse.microprofile.config.spi.ConfigProviderResolver with io.helidon.config.MpConfigProviderResolver;
}

View File

@@ -1,17 +0,0 @@
#
# Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
io.helidon.config.internal.ConfigFileTypeDetector

View File

@@ -1,37 +0,0 @@
/*
* Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.helidon.config.internal;
import java.nio.file.Paths;
import io.helidon.config.ConfigHelper;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
/**
* Tests {@link ConfigFileTypeDetector}.
*/
public class ConfigFileTypeDetectorTest {
@Test
public void testProbeContentTypeProperties() {
assertThat(ConfigHelper.detectContentType(Paths.get("config.properties")), is("text/x-java-properties"));
}
}

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2017, 2020 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -45,6 +45,10 @@
<groupId>io.helidon.common</groupId>
<artifactId>helidon-common</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.common</groupId>
<artifactId>helidon-common-media-type</artifactId>
</dependency>
<!-- etcd v2 -->
<dependency>

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,15 +18,14 @@ package io.helidon.config.etcd;
import java.io.StringReader;
import java.net.URI;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.helidon.common.HelidonFeatures;
import io.helidon.common.media.type.MediaTypes;
import io.helidon.config.Config;
import io.helidon.config.ConfigException;
import io.helidon.config.ConfigHelper;
import io.helidon.config.etcd.EtcdConfigSourceBuilder.EtcdEndpoint;
import io.helidon.config.etcd.internal.client.EtcdClient;
import io.helidon.config.etcd.internal.client.EtcdClientException;
@@ -68,7 +67,7 @@ public class EtcdConfigSource extends AbstractParsableConfigSource<Long> {
}
private Optional<String> probeContentType() {
return Optional.ofNullable(ConfigHelper.detectContentType(Paths.get(endpoint.key())));
return MediaTypes.detectType(endpoint.key());
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ module io.helidon.config.etcd {
requires com.google.protobuf;
requires com.google.common;
requires io.helidon.common;
requires io.helidon.common.media.type;
exports io.helidon.config.etcd;

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2017, 2020 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -46,6 +46,10 @@
<groupId>io.helidon.common</groupId>
<artifactId>helidon-common</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.common</groupId>
<artifactId>helidon-common-media-type</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,9 +34,9 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import io.helidon.common.HelidonFeatures;
import io.helidon.common.media.type.MediaTypes;
import io.helidon.config.Config;
import io.helidon.config.ConfigException;
import io.helidon.config.ConfigHelper;
import io.helidon.config.internal.FileSourceHelper;
import io.helidon.config.spi.AbstractParsableConfigSource;
import io.helidon.config.spi.ConfigParser;
@@ -236,7 +236,7 @@ public class GitConfigSource extends AbstractParsableConfigSource<byte[]> {
}
private Optional<String> probeContentType() {
return Optional.ofNullable(ConfigHelper.detectContentType(targetPath));
return MediaTypes.detectType(targetPath);
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ module io.helidon.config.git {
requires java.logging;
requires org.eclipse.jgit;
requires io.helidon.common;
requires io.helidon.common.media.type;
exports io.helidon.config.git;

View File

@@ -1,40 +0,0 @@
/*
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.helidon.config.hocon.internal;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.spi.FileTypeDetector;
/**
* Custom implementation of Java {@link FileTypeDetector} to support HOCON and JSON formats.
*/
public class HoconFileTypeDetector extends FileTypeDetector {
@Override
public String probeContentType(Path path) throws IOException {
String resourceUri = path.toString();
if (resourceUri.indexOf('.') != -1) {
String fileExt = resourceUri.substring(resourceUri.lastIndexOf('.'));
if (fileExt.equals(".conf")) {
return HoconConfigParser.MEDIA_TYPE_APPLICATION_HOCON;
} else if (fileExt.equals(".json")) {
return HoconConfigParser.MEDIA_TYPE_APPLICATION_JSON;
}
}
return null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,5 @@ module io.helidon.config.hocon {
exports io.helidon.config.hocon;
provides io.helidon.config.spi.ConfigParser with io.helidon.config.hocon.internal.HoconConfigParser;
provides java.nio.file.spi.FileTypeDetector with io.helidon.config.hocon.internal.HoconFileTypeDetector;
}

View File

@@ -1,17 +0,0 @@
#
# Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
io.helidon.config.hocon.internal.HoconFileTypeDetector

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,39 +16,29 @@
package io.helidon.config.hocon.internal;
import java.io.IOException;
import java.nio.file.Paths;
import io.helidon.config.ConfigHelper;
import io.helidon.common.media.type.MediaTypes;
import org.junit.jupiter.api.Test;
import static io.helidon.config.testing.OptionalMatcher.value;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* Tests {@link HoconFileTypeDetector}.
* File type detector for hocon is now obsolete.
* Tests left in to make sure we detect these types as expected
*/
public class HoconFileTypeDetectorTest {
@Test
public void testProbeContentTypeHocon() throws IOException {
assertThat(ConfigHelper.detectContentType(Paths.get("config.conf")), is("application/hocon"));
public void testProbeContentTypeHocon() {
assertThat(MediaTypes.detectType(Paths.get("config.conf")), value(is("application/hocon")));
}
@Test
public void testProbeContentTypeHoconDirectly() throws IOException {
assertThat(new HoconFileTypeDetector().probeContentType(Paths.get("config.conf")), is("application/hocon"));
public void testProbeContentTypeJson() {
assertThat(MediaTypes.detectType(Paths.get("config.json")), value(is("application/json")));
}
@Test
public void testProbeContentTypeJson() throws IOException {
assertThat(ConfigHelper.detectContentType(Paths.get("config.json")), is("application/json"));
}
@Test
public void testProbeContentTypeJsonDirectly() throws IOException {
assertThat(new HoconFileTypeDetector().probeContentType(Paths.get("config.json")), is("application/json"));
}
}

View File

@@ -1,38 +0,0 @@
/*
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.helidon.config.yaml.internal;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.spi.FileTypeDetector;
/**
* Custom implementation of Java {@link FileTypeDetector} to support YAML format.
*/
public class YamlFileTypeDetector extends FileTypeDetector {
@Override
public String probeContentType(Path path) throws IOException {
String resourceUri = path.toString();
if (resourceUri.indexOf('.') != -1) {
String fileExt = resourceUri.substring(resourceUri.lastIndexOf('.'));
if (fileExt.equals(".yaml")) {
return YamlConfigParser.MEDIA_TYPE_APPLICATION_YAML;
}
}
return null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,5 @@ module io.helidon.config.yaml {
exports io.helidon.config.yaml;
provides io.helidon.config.spi.ConfigParser with io.helidon.config.yaml.internal.YamlConfigParser;
provides java.nio.file.spi.FileTypeDetector with io.helidon.config.yaml.internal.YamlFileTypeDetector;
}

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2019, 2020 Oracle and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,5 +18,4 @@
# Graal native image supports additional configuration from this property file.
# Snake yaml uses reflection to instantiate a map.
#
Args=-H:ReflectionConfigurationResources=${.}/helidon-config-yaml-reflection-config.json \
--initialize-at-build-time=io.helidon.config.yaml.internal.YamlFileTypeDetector
Args=--initialize-at-build-time=io.helidon.config.yaml

View File

@@ -1,17 +0,0 @@
#
# Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
io.helidon.config.yaml.internal.YamlFileTypeDetector

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,24 +16,24 @@
package io.helidon.config.yaml.internal;
import java.io.IOException;
import java.nio.file.Paths;
import io.helidon.config.ConfigHelper;
import io.helidon.common.media.type.MediaTypes;
import org.junit.jupiter.api.Test;
import static io.helidon.config.testing.OptionalMatcher.value;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
/**
* Tests {@link YamlFileTypeDetector}.
* Test left in to make sure we correctly evaluate yaml file type suffix.
*/
public class YamlFileTypeDetectorTest {
@Test
public void testProbeContentType() throws IOException {
assertThat(ConfigHelper.detectContentType(Paths.get("config.yaml")), is("application/x-yaml"));
public void testProbeContentType() {
assertThat(MediaTypes.detectType(Paths.get("config.yaml")), value(is("application/x-yaml")));
}
}