use of org.apache.jackrabbit.oak.remote.RemoteBinaryFilters in project jackrabbit-oak by apache.
the class ContentRemoteSessionTest method testReadBinary.
@Test
public void testReadBinary() {
Blob blob = mock(Blob.class);
ContentRemoteBinaryId binaryId = mock(ContentRemoteBinaryId.class);
doReturn(blob).when(binaryId).asBlob();
assertNotNull(createSession().readBinary(binaryId, new RemoteBinaryFilters()));
}
use of org.apache.jackrabbit.oak.remote.RemoteBinaryFilters in project jackrabbit-oak by apache.
the class GetBinaryHandler method parseRange.
/**
* Parse a range extracted from the Range header and return a wrapped
* RemoteBinaryFilters instance for the range or null if the range is not
* valid or malformed.
* <p/>
* The returned RemoteBinaryFilters object will never return -1 in
* getCount.
*/
private RemoteBinaryFilters parseRange(String range, long fileLength) {
Matcher matcher = RANGE_PATTERN.matcher(range);
if (!matcher.matches()) {
return null;
}
final long start;
final long end;
// Content-Range: X
if (matcher.group(2) == null || matcher.group(2).isEmpty()) {
start = Long.parseLong(matcher.group(1));
end = fileLength - 1;
} else // Content-Range: -X
if (matcher.group(1).isEmpty()) {
end = fileLength - 1;
start = end - Long.parseLong(matcher.group(2)) + 1;
} else // Content-Range: X-Y
{
start = Long.parseLong(matcher.group(1));
end = Long.parseLong(matcher.group(2));
}
// Simple range validation
if (start < 0 || end < 0 || start > end || end >= fileLength || start >= fileLength) {
return null;
}
return new RemoteBinaryFilters() {
@Override
public long getStart() {
return start;
}
@Override
public long getCount() {
return end - start + 1;
}
};
}
use of org.apache.jackrabbit.oak.remote.RemoteBinaryFilters in project jackrabbit-oak by apache.
the class GetBinaryHandler method handle.
@Override
public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
RemoteSession session = (RemoteSession) request.getAttribute("session");
if (session == null) {
sendInternalServerError(response, "session not found");
return;
}
String providedBinaryId = readBinaryId(request);
if (providedBinaryId == null) {
sendBadRequest(response, "unable to read the provided binary ID");
return;
}
RemoteBinaryId binaryId = session.readBinaryId(providedBinaryId);
if (binaryId == null) {
sendNotFound(response, "binary ID not found");
return;
}
List<RemoteBinaryFilters> contentRanges = parseRequestRanges(request, session, binaryId);
if (contentRanges == null) {
handleFile(response, session, binaryId);
} else if (contentRanges.size() == 1) {
handleSingleRange(response, session, binaryId, contentRanges.get(0));
} else {
handleMultipleRanges(response, session, binaryId, contentRanges);
}
}
use of org.apache.jackrabbit.oak.remote.RemoteBinaryFilters in project jackrabbit-oak by apache.
the class GetBinaryHandler method handleMultipleRanges.
/**
* RFC7233
* <p/>
* This handler sends a 206 Partial Content http status, the Content-Length
* header, Content-Type multipart/byteranges The payload contains all the
* requested binary fragments.
* <p/>
* This handler is used when multiple ranges are requested.
*/
private void handleMultipleRanges(HttpServletResponse response, RemoteSession session, RemoteBinaryId binaryId, List<RemoteBinaryFilters> ranges) throws IOException {
String header;
long rangeStart, rangeEnd, fileLength, contentLength;
fileLength = session.readBinaryLength(binaryId);
// Compute response content length
// Create multipart headers
contentLength = 0;
List<String> multipartHeaders = new ArrayList<String>(ranges.size());
for (RemoteBinaryFilters range : ranges) {
rangeStart = range.getStart();
rangeEnd = rangeStart + range.getCount() - 1;
header = String.format("\n" + "--%s\n" + "Content-Type: application/octet-stream" + "Content-Content-Range: %d-%d/%d\n\n", MULTIPART_DELIMITER, rangeStart, rangeEnd, fileLength);
multipartHeaders.add(header);
contentLength += header.getBytes().length;
contentLength += range.getCount();
}
// Send response status and headers
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
response.setContentLength((int) contentLength);
response.setContentType("multipart/byteranges; boundary=" + MULTIPART_DELIMITER);
// Send requested ranges
RemoteBinaryFilters range;
InputStream in;
OutputStream out = response.getOutputStream();
Iterator<RemoteBinaryFilters> rangeIt = ranges.iterator();
Iterator<String> headerIt = multipartHeaders.iterator();
while (rangeIt.hasNext() && headerIt.hasNext()) {
range = rangeIt.next();
header = headerIt.next();
out.write(header.getBytes());
in = session.readBinary(binaryId, range);
ByteStreams.copy(in, out);
}
out.close();
}
use of org.apache.jackrabbit.oak.remote.RemoteBinaryFilters in project jackrabbit-oak by apache.
the class GetBinaryHandler method parseRequestRanges.
/**
* This method parses the request Range header a list of ranges as
* RemoteBinaryFilters ( or null when the header is missing or contains
* invalid/malformed values
*/
private List<RemoteBinaryFilters> parseRequestRanges(HttpServletRequest request, RemoteSession session, RemoteBinaryId binaryId) {
// Check header exists
String headerValue = request.getHeader(RANGE_HEADER);
if (headerValue == null) {
return null;
}
// Check header is bytes=*
Matcher matcher = RANGE_HEADER_PATTERN.matcher(headerValue);
if (!matcher.matches()) {
return null;
}
// Iterate requested ranges
headerValue = matcher.group(1);
StringTokenizer tokenizer = new StringTokenizer(headerValue, ",");
List<RemoteBinaryFilters> ranges = new LinkedList<RemoteBinaryFilters>();
RemoteBinaryFilters range;
long fileLength = session.readBinaryLength(binaryId);
while (tokenizer.hasMoreTokens()) {
range = parseRange(tokenizer.nextToken(), fileLength);
if (range == null) {
return null;
}
ranges.add(range);
}
return ranges;
}
Aggregations