Minor code improvements
Signed-off-by: Dominic Schabel dominic.schabel@bosch-si.com
This commit is contained in:
@@ -9,11 +9,24 @@
|
||||
package org.eclipse.hawkbit.rest.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.net.HttpHeaders.ACCEPT_RANGES;
|
||||
import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION;
|
||||
import static com.google.common.net.HttpHeaders.CONTENT_LENGTH;
|
||||
import static com.google.common.net.HttpHeaders.CONTENT_RANGE;
|
||||
import static com.google.common.net.HttpHeaders.ETAG;
|
||||
import static com.google.common.net.HttpHeaders.IF_RANGE;
|
||||
import static com.google.common.net.HttpHeaders.LAST_MODIFIED;
|
||||
import static java.math.RoundingMode.DOWN;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT;
|
||||
import static org.eclipse.hawkbit.rest.util.ByteRange.MULTIPART_BOUNDARY;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.springframework.http.HttpStatus.PARTIAL_CONTENT;
|
||||
import static org.springframework.http.HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE;
|
||||
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -27,23 +40,19 @@ import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import com.google.common.math.DoubleMath;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
/**
|
||||
* Utility class for the Rest Source API.
|
||||
*
|
||||
*/
|
||||
public final class RestResourceConversionHelper {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RestResourceConversionHelper.class);
|
||||
|
||||
private static final int BUFFER_SIZE = 4096;
|
||||
|
||||
// utility class, private constructor.
|
||||
private RestResourceConversionHelper() {
|
||||
|
||||
}
|
||||
@@ -92,7 +101,8 @@ public final class RestResourceConversionHelper {
|
||||
*
|
||||
* @return http code
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7233
|
||||
* @see <a href="https://tools.ietf.org/html/rfc7233">https://tools.ietf.org
|
||||
* /html/rfc7233</a>
|
||||
*/
|
||||
public static ResponseEntity<InputStream> writeFileResponse(final LocalArtifact artifact,
|
||||
final HttpServletResponse response, final HttpServletRequest request, final DbArtifact file,
|
||||
@@ -107,11 +117,11 @@ public final class RestResourceConversionHelper {
|
||||
|
||||
response.reset();
|
||||
response.setBufferSize(BUFFER_SIZE);
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + artifact.getFilename());
|
||||
response.setHeader(HttpHeaders.ETAG, etag);
|
||||
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
|
||||
response.setDateHeader(HttpHeaders.LAST_MODIFIED, lastModified);
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
response.setHeader(CONTENT_DISPOSITION, "attachment;filename=" + artifact.getFilename());
|
||||
response.setHeader(ETAG, etag);
|
||||
response.setHeader(ACCEPT_RANGES, "bytes");
|
||||
response.setDateHeader(LAST_MODIFIED, lastModified);
|
||||
response.setContentType(APPLICATION_OCTET_STREAM_VALUE);
|
||||
|
||||
final ByteRange full = new ByteRange(0, length - 1, length);
|
||||
final List<ByteRange> ranges = new ArrayList<>();
|
||||
@@ -123,9 +133,9 @@ public final class RestResourceConversionHelper {
|
||||
|
||||
// Range header matches"bytes=n-n,n-n,n-n..."
|
||||
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
|
||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + length);
|
||||
response.setHeader(CONTENT_RANGE, "bytes */" + length);
|
||||
LOG.debug("range header for filename ({}) is not satisfiable: ", artifact.getFilename());
|
||||
return new ResponseEntity<>(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
return new ResponseEntity<>(REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
}
|
||||
|
||||
// RFC: if the representation is unchanged, send me the part(s) that
|
||||
@@ -144,32 +154,31 @@ public final class RestResourceConversionHelper {
|
||||
// full request - no range
|
||||
if (ranges.isEmpty() || ranges.get(0).equals(full)) {
|
||||
LOG.debug("filename ({}) results into a full request: ", artifact.getFilename());
|
||||
fullfileRequest(artifact, response, file, controllerManagement, statusId, full);
|
||||
result = new ResponseEntity<>(HttpStatus.OK);
|
||||
handleFullFileRequest(artifact, response, file, controllerManagement, statusId, full);
|
||||
result = new ResponseEntity<>(OK);
|
||||
}
|
||||
// standard range request
|
||||
else if (ranges.size() == 1) {
|
||||
LOG.debug("filename ({}) results into a standard range request: ", artifact.getFilename());
|
||||
standardRangeRequest(artifact, response, file, controllerManagement, statusId, ranges);
|
||||
result = new ResponseEntity<>(HttpStatus.PARTIAL_CONTENT);
|
||||
handleStandardRangeRequest(artifact, response, file, controllerManagement, statusId, ranges);
|
||||
result = new ResponseEntity<>(PARTIAL_CONTENT);
|
||||
}
|
||||
// multipart range request
|
||||
else {
|
||||
LOG.debug("filename ({}) results into a multipart range request: ", artifact.getFilename());
|
||||
multipartRangeRequest(artifact, response, file, controllerManagement, statusId, ranges);
|
||||
result = new ResponseEntity<>(HttpStatus.PARTIAL_CONTENT);
|
||||
handleMultipartRangeRequest(artifact, response, file, controllerManagement, statusId, ranges);
|
||||
result = new ResponseEntity<>(PARTIAL_CONTENT);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private static void fullfileRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||
private static void handleFullFileRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
||||
final ByteRange full) {
|
||||
final ByteRange r = full;
|
||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(r.getLength()));
|
||||
response.setHeader(CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||
response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength()));
|
||||
|
||||
try {
|
||||
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
||||
@@ -182,7 +191,7 @@ public final class RestResourceConversionHelper {
|
||||
|
||||
private static ResponseEntity<InputStream> extractRange(final HttpServletResponse response, final long length,
|
||||
final List<ByteRange> ranges, final String range) {
|
||||
ResponseEntity<InputStream> result = null;
|
||||
|
||||
if (ranges.isEmpty()) {
|
||||
for (final String part : range.substring(6).split(",")) {
|
||||
long start = sublong(part, 0, part.indexOf('-'));
|
||||
@@ -198,9 +207,8 @@ public final class RestResourceConversionHelper {
|
||||
// Check if Range is syntactically valid. If not, then return
|
||||
// 416.
|
||||
if (start > end) {
|
||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + length);
|
||||
result = new ResponseEntity<>(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
return result;
|
||||
response.setHeader(CONTENT_RANGE, "bytes */" + length);
|
||||
return new ResponseEntity<>(REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||
}
|
||||
|
||||
// Add range.
|
||||
@@ -218,10 +226,10 @@ public final class RestResourceConversionHelper {
|
||||
|
||||
private static void checkForShortcut(final HttpServletRequest request, final String etag, final long lastModified,
|
||||
final ByteRange full, final List<ByteRange> ranges) {
|
||||
final String ifRange = request.getHeader(HttpHeaders.IF_RANGE);
|
||||
final String ifRange = request.getHeader(IF_RANGE);
|
||||
if (ifRange != null && !ifRange.equals(etag)) {
|
||||
try {
|
||||
final long ifRangeTime = request.getDateHeader(HttpHeaders.IF_RANGE);
|
||||
final long ifRangeTime = request.getDateHeader(IF_RANGE);
|
||||
if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) {
|
||||
ranges.add(full);
|
||||
}
|
||||
@@ -232,17 +240,17 @@ public final class RestResourceConversionHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private static void multipartRangeRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||
private static void handleMultipartRangeRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
||||
final List<ByteRange> ranges) {
|
||||
response.setContentType("multipart/byteranges; boundary=" + ByteRange.MULTIPART_BOUNDARY);
|
||||
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
||||
response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
|
||||
response.setStatus(SC_PARTIAL_CONTENT);
|
||||
|
||||
try {
|
||||
for (final ByteRange r : ranges) {
|
||||
// Add multipart boundary and header fields for every range.
|
||||
response.getOutputStream().println();
|
||||
response.getOutputStream().println("--" + ByteRange.MULTIPART_BOUNDARY);
|
||||
response.getOutputStream().println("--" + MULTIPART_BOUNDARY);
|
||||
response.getOutputStream()
|
||||
.println("Content-Range: bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||
|
||||
@@ -253,20 +261,20 @@ public final class RestResourceConversionHelper {
|
||||
|
||||
// End with final multipart boundary.
|
||||
response.getOutputStream().println();
|
||||
response.getOutputStream().print("--" + ByteRange.MULTIPART_BOUNDARY + "--");
|
||||
response.getOutputStream().print("--" + MULTIPART_BOUNDARY + "--");
|
||||
} catch (final IOException e) {
|
||||
LOG.error("multipartRangeRequest of file ({}) failed!", artifact.getFilename(), e);
|
||||
throw new FileSteamingFailedException(artifact.getFilename());
|
||||
}
|
||||
}
|
||||
|
||||
private static void standardRangeRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||
private static void handleStandardRangeRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
||||
final List<ByteRange> ranges) {
|
||||
final ByteRange r = ranges.get(0);
|
||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(r.getLength()));
|
||||
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
||||
response.setHeader(CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||
response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength()));
|
||||
response.setStatus(SC_PARTIAL_CONTENT);
|
||||
|
||||
try {
|
||||
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
||||
@@ -315,7 +323,7 @@ public final class RestResourceConversionHelper {
|
||||
}
|
||||
|
||||
if (controllerManagement != null) {
|
||||
final int newPercent = DoubleMath.roundToInt(total * 100.0 / length, RoundingMode.DOWN);
|
||||
final int newPercent = DoubleMath.roundToInt(total * 100.0 / length, DOWN);
|
||||
|
||||
// every 10 percent an event
|
||||
if (newPercent == 100 || newPercent > progressPercent + 10) {
|
||||
|
||||
Reference in New Issue
Block a user