Skip to content

Commit

Permalink
update ResourceRequestHandler (youngmonkeys#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
tvd12 authored Oct 4, 2022
1 parent efca264 commit a9a2ede
Show file tree
Hide file tree
Showing 16 changed files with 989 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package com.tvd12.ezyhttp.core.constant;

import java.util.Map;

import com.tvd12.ezyfox.util.EzyEnums;

import lombok.Getter;

import java.util.Map;

@Getter
public enum ContentType {

AAC_AUDIO(ContentTypes.AAC_AUDIO, "aac"),
ABI_WORD_DOCUMENT(ContentTypes.ABI_WORD_DOCUMENT, "abw"),
ARCHIVE_DOCUMENT(ContentTypes.ARCHIVE_DOCUMENT, "arc"),
AUDIO_VIDEO_INTERLEAVE(ContentTypes.AUDIO_VIDEO_INTERLEAVE, "avi"),
AMAZONE_KINDLE_EBOOK(ContentTypes.AMAZONE_KINDLE_EBOOK, "azw"),
AMAZON_KINDLE_EBOOK(ContentTypes.AMAZONE_KINDLE_EBOOK, "azw"),
BZIP(ContentTypes.BZIP, "bz"),
BZIP2(ContentTypes.BZIP2, "bz2"),
CD_AUDIO(ContentTypes.CD_AUDIO, "cda"),
Expand Down Expand Up @@ -98,6 +97,9 @@ public enum ContentType {
private final String extension;
private final String value;

private static final Map<String, ContentType> VALUE_BY_MIME_TYPE =
EzyEnums.enumMap(ContentType.class, it -> it.value);

private static final Map<String, ContentType> VALUE_BY_EXTENSION =
EzyEnums.enumMap(ContentType.class, it -> it.extension);

Expand All @@ -106,11 +108,29 @@ public enum ContentType {
this.extension = extension;
}

public String getMimeType() {
return value;
}

public static ContentType ofMimeType(String mimeType) {
return VALUE_BY_MIME_TYPE.get(mimeType);
}

public static ContentType ofExtension(String extension) {
ContentType value = VALUE_BY_EXTENSION.get(extension);
if (value == null) {
value = APPLICATION_OCTET_STREAM;
return VALUE_BY_EXTENSION.getOrDefault(
extension,
APPLICATION_OCTET_STREAM
);
}

public static String getExtensionOfMimeType(
String mimeType,
String defaultExtension
) {
ContentType contentType = VALUE_BY_MIME_TYPE.get(mimeType);
if (contentType != null) {
return contentType.getExtension();
}
return value;
return defaultExtension;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

public final class Headers {

public static final String ACCEPT_RANGES = "accept-ranges";
public static final String CONTENT_RANGE = "Content-Range";
public static final String CONTENT_LENGTH = "Content-Length";
public static final String CONTENT_TYPE = "Content-Type";

private Headers() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public final class StatusCodes {
public static final int CREATED = 201;
public static final int ACCEPTED = 202;
public static final int NO_CONTENT = 204;
public static final int PARTIAL_CONTENT = 206;
public static final int MOVED_PERMANENTLY = 301;
public static final int MOVED_TEMPORARILY = 302;
public static final int BAD_REQUEST = 400;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.tvd12.ezyhttp.core.data;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class BytesRange {
private final long from;
private final long to;

public BytesRange(String range) {
this(extractRange(range));
}

public BytesRange(String[] fromTo) {
this(
Long.parseLong(fromTo[0].trim()),
fromTo.length == 1 ? 0 : Long.parseLong(fromTo[1].trim())
);
}

private static String[] extractRange(String range) {
final int equalsIndex = range.indexOf('=');
String actualRange = range;
if (equalsIndex >= 0) {
actualRange = range
.substring(equalsIndex + 1)
.trim();
}
final int dashIndex = actualRange.lastIndexOf('-');
if (dashIndex <= 0) {
return new String[] { actualRange };
}
if (dashIndex >= actualRange.length() - 1) {
return new String[] {
actualRange.substring(0, dashIndex)
};
}
return new String[] {
actualRange.substring(0, dashIndex).trim(),
actualRange.substring(dashIndex + 1).trim()
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.tvd12.ezyhttp.core.io;

import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class AnywayFileLoader {

private final List<Function<String, File>> loaders =
Arrays.asList(
File::new,
filePath -> newFileFromUrl(
getClass().getResource(filePath)
),
filePath -> newFileFromUrl(
getClass().getClassLoader().getResource(filePath)
),
filePath -> newFileFromUrl(
getClass().getResource('/' + filePath)
),
filePath -> newFileFromUrl(
getClass().getClassLoader().getResource('/' + filePath)
),
filePath -> newFileFromUrl(
Thread.currentThread().getContextClassLoader().getResource(filePath)
),
filePath -> newFileFromUrl(
Thread.currentThread().getContextClassLoader().getResource('/' + filePath)
)
);

public File load(String filePath) {
for (Function<String, File> loader : loaders) {
final File file = loader.apply(filePath);
if (file != null && file.exists()) {
return file;
}
}
return null;
}

private static File newFileFromUrl(URL fileUrl) {
return fileUrl != null ? new File(fileUrl.getFile()) : null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.tvd12.ezyhttp.core.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;

import com.tvd12.ezyhttp.core.data.BytesRange;

import lombok.Getter;

public class BytesRangeFileInputStream extends InputStream {

@Getter
private final long from;
@Getter
private final long to;
@Getter
private final long fileLength;
@Getter
private long readBytes;
@Getter
private final long targetReadBytes;
private final RandomAccessFile randomAccessFile;

public static final int MAX_CHUNK_LENGTH = 2 * 1024 * 1024;

public BytesRangeFileInputStream(
String filePath,
String range
) throws Exception {
this(filePath, new BytesRange(range));
}

public BytesRangeFileInputStream(
String filePath,
BytesRange range
) throws Exception {
this(
filePath,
range.getFrom(),
range.getTo()
);
}

public BytesRangeFileInputStream(
String filePath,
long rangeFrom,
long rangeTo
) throws Exception {
from = rangeFrom;
final AnywayFileLoader fileLoader = new AnywayFileLoader();
final File file = fileLoader.load(filePath);
if (file == null) {
throw new FileNotFoundException(filePath + " not found");
}
fileLength = file.length();
long actualTo = rangeTo == 0
? from + MAX_CHUNK_LENGTH
: rangeTo + 1;
if (actualTo > fileLength) {
actualTo = fileLength;
}
to = actualTo;
targetReadBytes = actualTo - from;
randomAccessFile = new RandomAccessFile(
file,
"r"
);
try {
randomAccessFile.seek(from);
} catch (Exception e) {
randomAccessFile.close();
throw e;
}
}

@Override
public int read(byte[] b) throws IOException {
if (readBytes >= targetReadBytes) {
return -1;
}
final int length = (int) (to - (from + readBytes));
final int actualLength = Math.min(b.length, length);
final int rb = randomAccessFile.read(b, 0, actualLength);
if (rb > 0) {
readBytes += rb;
}
return rb;
}

@Override
public int read() throws IOException {
if (readBytes >= targetReadBytes) {
return -1;
}
final int b = randomAccessFile.read();
if (b >= 0) {
++readBytes;
}
return b;
}

@Override
public void close() throws IOException {
randomAccessFile.close();
}

public String getBytesContentRangeString() {
return "bytes " + from +
'-' + (from < to ? to - 1 : to) +
'/' + fileLength;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tvd12.ezyhttp.core.resources;

import java.io.EOFException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.BlockingQueue;
Expand Down Expand Up @@ -92,6 +93,9 @@ private void loop() {
outputStream.write(buffer, 0, read);
done = false;
}
} catch (EOFException e) {
exception = e;
logger.info("download's broken cause by output stream has closed");
} catch (Exception e) {
exception = e;
logger.info("download error", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ private void loop() {
}
} catch (Exception e) {
exception = e;
logger.info("upload error", e);
logger.info("upload broken", e);
} catch (Throwable e) {
exception = new IllegalStateException(e);
logger.info("upload fatal error", e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.tvd12.ezyhttp.core.test.constant;

import org.testng.annotations.Test;

import com.tvd12.ezyhttp.core.constant.ContentType;
import com.tvd12.ezyhttp.core.constant.ContentTypes;
import com.tvd12.test.assertion.Asserts;
import org.testng.annotations.Test;

public class ContentTypeTest {

Expand All @@ -30,11 +29,48 @@ public void ofExtensionTest() {
Asserts.assertEquals(ContentType.ofExtension("html"), ContentType.TEXT_HTML_UTF8);
Asserts.assertEquals(ContentType.ofExtension("txt"), ContentType.TEXT_PLAIN);
Asserts.assertEquals(ContentType.ofExtension(null), ContentType.APPLICATION_OCTET_STREAM);

Asserts.assertEquals(ContentType.ofMimeType(ContentTypes.MP3), ContentType.MP3);
Asserts.assertNull(ContentType.ofMimeType("not found"));
Asserts.assertEquals(
ContentType.MP3.getValue(),
ContentType.MP3.getMimeType()
);
}

@Test
public void commonTest() {
Asserts.assertEquals("json", ContentType.APPLICATION_JSON.getExtension());
Asserts.assertEquals(ContentTypes.APPLICATION_JSON, ContentType.APPLICATION_JSON.getValue());
}

@Test
public void getExtensionOfMimeTypeTest() {
// given
String defaultExtension = "mp3";

// when
String actual = ContentType.getExtensionOfMimeType(
ContentTypes.MP3,
defaultExtension
);

// then
Asserts.assertEquals(actual, ContentType.MP3.getExtension());
}

@Test
public void getExtensionOfMimeTypeButDefaultTest() {
// given
String defaultExtension = "mp3";

// when
String actual = ContentType.getExtensionOfMimeType(
"not found",
defaultExtension
);

// then
Asserts.assertEquals(actual, defaultExtension);
}
}
Loading

0 comments on commit a9a2ede

Please sign in to comment.