Skip to content

Commit

Permalink
Extend ContentType class functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
HardNorth committed Apr 4, 2024
1 parent 7f3dde5 commit cd487ad
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Changelog

## [Unreleased]
### Changed
- Extend `ContentType` class functionality, by @HardNorth

## [5.2.11]
### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ public static TypeAwareByteSource convertIfImage(TypeAwareByteSource content) {
* @throws IOException In case of IO exception
*/
public static TypeAwareByteSource convert(ByteSource source) throws IOException {
BufferedImage image;
image = ImageIO.read(source.openBufferedStream());
BufferedImage image = ImageIO.read(source.openBufferedStream());
final BufferedImage blackAndWhiteImage = new BufferedImage(image.getWidth(null),
image.getHeight(null),
BufferedImage.TYPE_BYTE_GRAY
Expand Down Expand Up @@ -82,7 +81,7 @@ public static boolean isImage(TypeAwareByteSource source) {
* @return true if image
*/
public static boolean isImage(String contentType) {
return ofNullable(ContentType.parse(contentType)).map(type -> type.startsWith(IMAGE_TYPE)).orElse(false);
return ofNullable(ContentType.stripMediaType(contentType)).map(type -> type.startsWith(IMAGE_TYPE)).orElse(false);
}

/**
Expand Down
61 changes: 60 additions & 1 deletion src/main/java/com/epam/reportportal/utils/http/ContentType.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,49 @@
package com.epam.reportportal.utils.http;

import javax.annotation.Nullable;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* Content-Type header constants and utility methods.
*/
@SuppressWarnings("unused")
public class ContentType {
private static final Pattern HTTP_HEADER_DELIMITER_PATTERN = Pattern.compile("[=;,]");
private static final String TOKEN = "[0-9A-Za-z!#$%&'*+.^_`|~-]+";
private static final String TYPE = "(application|audio|font|example|image|message|model|multipart|text|video|x-" + TOKEN + ")";
private static final String MEDIA_TYPE = TYPE + "/" + "(" + TOKEN + ")";
private static final Pattern MEDIA_TYPE_PATTERN = Pattern.compile(MEDIA_TYPE);

// Binary types
// Images
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_TIFF = "image/tiff";
public static final String IMAGE_WEBP = "image/webp";
public static final String IMAGE_X_ICON = "image/x-icon";
// Video
public static final String VIDEO_MPEG = "video/mpeg";
public static final String VIDEO_OGG = "video/ogg";
public static final String VIDEO_WEBM = "video/webm";
// Audio
public static final String AUDIO_MIDI = "audio/midi";
public static final String AUDIO_MPEG = "audio/mpeg";
public static final String AUDIO_OGG = "audio/ogg";
public static final String AUDIO_WEBM = "audio/webm";
public static final String AUDIO_WAV = "audio/wav";
// Archives
public static final String APPLICATION_JAVA_ARCHIVE = "application/java-archive";
public static final String APPLICATION_ZIP = "application/zip";
public static final String APPLICATION_GZIP = "application/gzip";
// Misc
public static final String APPLICATION_PDF = "application/pdf";
public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";

Expand All @@ -65,6 +85,21 @@ public class ContentType {
public static final String MULTIPART_DIGEST = "multipart/digest";
public static final String MULTIPART_PARALLEL = "multipart/parallel";

public static final Set<String> KNOWN_TYPES;

static {
KNOWN_TYPES = Collections.unmodifiableSet(Arrays.stream(ContentType.class.getFields())
.filter(f -> String.class.equals(f.getType()) && Modifier.isStatic(f.getModifiers()) && Modifier.isPublic(f.getModifiers()))
.map(f -> {
try {
return (String) f.get(null);
} catch (IllegalAccessException e) {
return null;
}
})
.collect(Collectors.toSet()));
}

private ContentType() {
throw new RuntimeException("No instances should exist for the class!");
}
Expand All @@ -76,7 +111,7 @@ private ContentType() {
* @return Media Type
*/
@Nullable
public static String parse(@Nullable String contentType) {
public static String stripMediaType(@Nullable String contentType) {
if (contentType == null || contentType.trim().isEmpty()) {
return null;
}
Expand All @@ -90,4 +125,28 @@ public static String parse(@Nullable String contentType) {
}
return mimeType.isEmpty() ? null : mimeType;
}

/**
* Check if the Media Type is known.
*
* @param mediaType Media Type value
* @return {@code true} if the Media Type is known, {@code false} otherwise
*/
public static boolean isKnownType(@Nullable String mediaType) {
return KNOWN_TYPES.contains(stripMediaType(mediaType));
}

/**
* Check if the Media Type is valid.
*
* @param mediaType Media Type value
* @return {@code true} if the Media Type is valid, {@code false} otherwise
*/
public static boolean isValidType(@Nullable String mediaType) {
if (mediaType == null || mediaType.trim().isEmpty()) {
return false;
}
String trimmed = mediaType.trim();
return MEDIA_TYPE_PATTERN.matcher(trimmed).matches();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@

import com.epam.reportportal.message.TypeAwareByteSource;
import com.epam.reportportal.utils.MimeTypeDetector;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;

import java.io.InputStream;
import java.util.Objects;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
Expand All @@ -29,14 +31,35 @@
* @author Andrei Varabyeu
*/
public class ImageConverterTest {
@Test
public void isImage() throws Exception {

private static TypeAwareByteSource getTestImage() throws Exception {
final String resourceName = "defaultUserPhoto.jpg";
InputStream stream = ImageConverterTest.class.getClassLoader().getResourceAsStream(resourceName);
assertThat("Image not found in path: " + resourceName, stream, notNullValue());
byte[] data = Utils.readInputStreamToBytes(stream);
final ByteSource byteSource = ByteSource.wrap(data);
boolean r = ImageConverter.isImage(new TypeAwareByteSource(byteSource, MimeTypeDetector.detect(byteSource, resourceName)));
assertThat("Incorrect image type detection", r, equalTo(true));
ByteSource data = ByteSource.wrap(Utils.readInputStreamToBytes(stream));
return new TypeAwareByteSource(data, MimeTypeDetector.detect(data, resourceName));
}

private static TypeAwareByteSource getTestFile() throws Exception {
final String resourceName = "hello.json";
InputStream stream = ImageConverterTest.class.getClassLoader().getResourceAsStream(resourceName);
assertThat("File not found in path: " + resourceName, stream, notNullValue());
ByteSource data = ByteSource.wrap(Utils.readInputStreamToBytes(stream));
return new TypeAwareByteSource(data, MimeTypeDetector.detect(data, resourceName));
}

@Test
public void isImage() throws Exception {
assertThat("Incorrect image type detection", ImageConverter.isImage(getTestImage()), equalTo(true));
assertThat("Incorrect image type detection", ImageConverter.isImage(getTestFile()), equalTo(false));
}

@Test
public void testImageConvert() throws Exception {
TypeAwareByteSource bwImage = ImageConverter.convertIfImage(getTestImage());
byte[] expectedImage = IOUtils.toByteArray(Objects.requireNonNull(ImageConverterTest.class.getClassLoader()
.getResourceAsStream("defaultUserPhoto_bw.png")));
assertThat("Image conversion failed", bwImage, notNullValue());
assertThat("Invalid result image", bwImage.read(), equalTo(expectedImage));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright 2024 EPAM Systems
*
* 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
*
* https://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 com.epam.reportportal.utils.http;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.Arrays;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class ContentTypeTest {
@Test
public void test_known_types() {
assertThat(ContentType.KNOWN_TYPES, allOf(hasItem("application/json"), hasItem("image/bmp"), hasItem("application/pdf")));
}

private static Iterable<Object[]> testIsKnownType() {
return Arrays.asList(
new Object[] { "application/json", true },
new Object[] { "application/pdf", true },
new Object[] { "image/bmp", true },
new Object[] { "video/vnd.iptvforum.2dparityfec-2005", false },
new Object[] { "", false },
new Object[] { " ", false },
new Object[] { "; charset=utf-8", false },
new Object[] { null, false }
);
}

@ParameterizedTest
@MethodSource("testIsKnownType")
public void test_is_known_type(String mediaType, boolean expected) {
assertThat(ContentType.isKnownType(mediaType), equalTo(expected));
}

private static Iterable<Object[]> testMediaTypeStripData() {
return Arrays.asList(
new Object[] { "application/json; charset=utf-8", "application/json" },
new Object[] { "", null },
new Object[] { " ", null },
new Object[] { "; charset=utf-8", null }
);
}

@ParameterizedTest
@MethodSource("testMediaTypeStripData")
public void test_media_type_strip(String contentType, String expected) {
assertThat(ContentType.stripMediaType(contentType), equalTo(expected));
}

private static Iterable<Object[]> testMediaTypeValid() {
return Arrays.asList(
new Object[] { "application/json", true },
new Object[] { "video/vnd.iptvforum.2dparityfec-2005", true },
new Object[] { "application/json; charset=utf-8", false },
new Object[] { "pdf", false },
new Object[] { " ", false },
new Object[] { "; charset=utf-8", false },
new Object[] { "", false },
new Object[] { null, false }
);
}

@ParameterizedTest
@MethodSource("testMediaTypeValid")
public void test_media_type_valid(String mediaType, boolean expected) {
assertThat(ContentType.isValidType(mediaType), equalTo(expected));
}
}

0 comments on commit cd487ad

Please sign in to comment.