Example usage for javax.servlet.http HttpServletResponse SC_REQUESTED_RANGE_NOT_SATISFIABLE

List of usage examples for javax.servlet.http HttpServletResponse SC_REQUESTED_RANGE_NOT_SATISFIABLE

Introduction

In this page you can find the example usage for javax.servlet.http HttpServletResponse SC_REQUESTED_RANGE_NOT_SATISFIABLE.

Prototype

int SC_REQUESTED_RANGE_NOT_SATISFIABLE

To view the source code for javax.servlet.http HttpServletResponse SC_REQUESTED_RANGE_NOT_SATISFIABLE.

Click Source Link

Document

Status code (416) indicating that the server cannot serve the requested byte range.

Usage

From source file:org.sakaiproject.nakamura.proxy.ICalProxyPostProcessor.java

/** 
 * Parse the response as an iCalendar feed, throwing an IOException if the response
 * is too long.//from ww w .  ja  va  2 s.c  o  m
 * @throws ResponseFailedException 
 * */
private Calendar loadCalendar(ProxyResponse response)
        throws IOException, ParserException, ResponseFailedException {

    // We won't bother checking the Content-Length header directly as it may not be 
    // present, we'll just count the number of bytes read from the input stream.
    LengthLimitingInputStream input = new LengthLimitingInputStream(response.getResponseBodyAsInputStream(),
            this.maxResponseLength);

    try {
        return new CalendarBuilder().build(input);
    }
    // The LengthLimitingInputStream throws a StreamLengthException when a read() pushes
    // the number of read bytes over the limit
    catch (StreamLengthException e) {
        throw new ResponseFailedException(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE,
                "The remote server's response was too long: " + e.getMessage());
    }
}

From source file:com.epam.catgenome.controller.util.MultipartFileSender.java

private List<Range> processRange(Long length, String fileName, Range full) throws IOException {
    // Prepare some variables. The full Range represents the complete file.
    List<Range> ranges = new ArrayList<>();

    // Validate and process Range and If-Range headers.
    String range = request.getHeader("Range");
    if (range != null) {

        // Range header should match format "bytes=n-n,n-n,n-n...". If not, then return 416.
        if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
            response.setHeader(CONTENT_RANGE_HEADER, "bytes */" + length); // Required in 416.
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }//from w  w  w .  ja  v  a2 s.c  o m

        String ifRange = request.getHeader("If-Range");
        if (ifRange != null && !ifRange.equals(fileName)) {
            try {
                long ifRangeTime = request.getDateHeader("If-Range"); // Throws IAE if invalid.
                if (ifRangeTime != -1) {
                    ranges.add(full);
                }
            } catch (IllegalArgumentException ignore) {
                ranges.add(full);
            }
        }

        // If any valid If-Range header, then process each part of byte range.
        if (ranges.isEmpty()) {
            for (String part : range.substring(6).split(",")) {
                // Assuming a file with length of 100, the following examples returns bytes at:
                // 50-80 (50 to 80), 40- (40 to length=100), -20 (length-20=80 to length=100).
                long start = Range.sublong(part, 0, part.indexOf('-'));
                long end = Range.sublong(part, part.indexOf('-') + 1, part.length());

                if (start == -1) {
                    start = length - end;
                    end = length - 1;
                } else if (end == -1 || end > length - 1) {
                    end = length - 1;
                }

                // Check if Range is syntactically valid. If not, then return 416.
                if (start > end) {
                    response.setHeader(CONTENT_RANGE_HEADER, "bytes */" + length); // Required in 416.
                    response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                    return null;
                }

                // Add range.
                ranges.add(new Range(start, end, length));
            }
        }
    }

    return ranges;
}

From source file:org.alfresco.repo.web.util.HttpRangeProcessor.java

/**
 * Process multiple ranges.//from   w w w. j av a  2s.com
 * 
 * @param res        HttpServletResponse
 * @param range      Range header value
 * @param ref        NodeRef to the content for streaming
 * @param property   Content Property for the content
 * @param mimetype   Mimetype of the content
 * @param userAgent  User Agent of the caller
 * 
 * @return true if processed range, false otherwise
 */
private boolean processMultiRange(Object res, String range, NodeRef ref, QName property, String mimetype,
        String userAgent) throws IOException {
    final Log logger = getLogger();

    // Handle either HttpServletResponse or WebScriptResponse
    HttpServletResponse httpServletResponse = null;
    WebScriptResponse webScriptResponse = null;
    if (res instanceof HttpServletResponse) {
        httpServletResponse = (HttpServletResponse) res;
    } else if (res instanceof WebScriptResponse) {
        webScriptResponse = (WebScriptResponse) res;
    }
    if (httpServletResponse == null && webScriptResponse == null) {
        // Unknown response object type
        return false;
    }

    // return the sets of bytes as requested in the content-range header
    // the response will be formatted as multipart/byteranges media type message

    /* Examples of byte-ranges-specifier values (assuming an entity-body of length 10000):
            
    - The first 500 bytes (byte offsets 0-499, inclusive):  bytes=0-499
    - The second 500 bytes (byte offsets 500-999, inclusive):
      bytes=500-999
    - The final 500 bytes (byte offsets 9500-9999, inclusive):
      bytes=-500
    - Or bytes=9500-
    - The first and last bytes only (bytes 0 and 9999):  bytes=0-0,-1
    - Several legal but not canonical specifications of byte offsets 500-999, inclusive:
       bytes=500-600,601-999
       bytes=500-700,601-999 */

    boolean processedRange = false;

    // get the content reader
    ContentReader reader = contentService.getReader(ref, property);

    final List<Range> ranges = new ArrayList<Range>(8);
    long entityLength = reader.getSize();
    for (StringTokenizer t = new StringTokenizer(range, ", "); t.hasMoreTokens(); /**/) {
        try {
            ranges.add(Range.constructRange(t.nextToken(), mimetype, entityLength));
        } catch (IllegalArgumentException err) {
            if (getLogger().isDebugEnabled())
                getLogger()
                        .debug("Failed to parse range header - returning 416 status code: " + err.getMessage());

            if (httpServletResponse != null) {
                httpServletResponse.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                httpServletResponse.setHeader(HEADER_CONTENT_RANGE, "\"*\"");
                httpServletResponse.getOutputStream().close();
            } else if (webScriptResponse != null) {
                webScriptResponse.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                webScriptResponse.setHeader(HEADER_CONTENT_RANGE, "\"*\"");
                webScriptResponse.getOutputStream().close();
            }
            return true;
        }
    }

    if (ranges.size() != 0) {
        // merge byte ranges if possible - IE handles this well, FireFox not so much
        if (userAgent == null || userAgent.indexOf("MSIE ") != -1) {
            Collections.sort(ranges);

            for (int i = 0; i < ranges.size() - 1; i++) {
                Range first = ranges.get(i);
                Range second = ranges.get(i + 1);
                if (first.end + 1 >= second.start) {
                    if (logger.isDebugEnabled())
                        logger.debug("Merging byte range: " + first + " with " + second);

                    if (first.end < second.end) {
                        // merge second range into first
                        first.end = second.end;
                    }
                    // else we simply discard the second range - it is contained within the first

                    // delete second range
                    ranges.remove(i + 1);
                    // reset loop index
                    i--;
                }
            }
        }

        // calculate response content length
        long length = MULTIPART_BYTERANGES_BOUNDRY_END.length() + 2;
        for (Range r : ranges) {
            length += r.getLength();
        }

        // output headers as we have at least one range to process
        OutputStream os = null;
        if (httpServletResponse != null) {
            httpServletResponse.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            httpServletResponse.setHeader(HEADER_CONTENT_TYPE, MULTIPART_BYTERANGES_HEADER);
            httpServletResponse.setHeader(HEADER_CONTENT_LENGTH, Long.toString(length));
            os = httpServletResponse.getOutputStream();
        } else if (webScriptResponse != null) {
            webScriptResponse.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            webScriptResponse.setHeader(HEADER_CONTENT_TYPE, MULTIPART_BYTERANGES_HEADER);
            webScriptResponse.setHeader(HEADER_CONTENT_LENGTH, Long.toString(length));
            os = webScriptResponse.getOutputStream();
        }

        InputStream is = null;
        try {
            for (Range r : ranges) {
                if (logger.isDebugEnabled())
                    logger.debug("Processing: " + r.getContentRange());

                try {
                    // output the header bytes for the range
                    if (os instanceof ServletOutputStream)
                        r.outputHeader((ServletOutputStream) os);

                    // output the binary data for the range
                    // need a new reader for each new InputStream
                    is = contentService.getReader(ref, property).getContentInputStream();
                    streamRangeBytes(r, is, os, 0L);
                    is.close();
                    is = null;

                    // section marker and flush stream
                    if (os instanceof ServletOutputStream)
                        ((ServletOutputStream) os).println();
                    os.flush();
                } catch (IOException err) {
                    if (getLogger().isDebugEnabled())
                        getLogger().debug(
                                "Unable to process multiple range due to IO Exception: " + err.getMessage());
                    throw err;
                }
            }
        } finally {
            if (is != null) {
                is.close();
            }
        }

        // end marker
        if (os instanceof ServletOutputStream)
            ((ServletOutputStream) os).println(MULTIPART_BYTERANGES_BOUNDRY_END);
        os.close();
        processedRange = true;
    }

    return processedRange;
}

From source file:org.dspace.app.rest.utils.MultipartFileSenderTest.java

/**
 * If the If-Match doesn't match the ETAG then return 416 Status code
 *
 * @throws Exception//ww  w. ja va2s .c o  m
 */
@Test
public void testIfMatchNoMatch() throws Exception {
    Long time = new Date().getTime();
    MultipartFileSender multipartFileSender = MultipartFileSender.fromInputStream(is).with(requestWrapper)
            .withFileName(fileName).with(responseWrapper).withChecksum(checksum).withMimetype(mimeType)
            .withLength(length).withLastModified(time);

    when(request.getDateHeader(eq("If-Modified-Since"))).thenReturn(-1L);
    when(request.getDateHeader(eq("If-Unmodified-Since"))).thenReturn(-1L);
    when(request.getHeader(eq("If-Match"))).thenReturn("None-Matching-ETAG");

    multipartFileSender.isValid();

    assertEquals(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, responseWrapper.getStatusCode());
}

From source file:org.dspace.app.rest.utils.MultipartFileSender.java

private List<Range> getRanges(final Range fullRange) throws IOException {
    List<Range> ranges = new ArrayList<>();

    // Validate and process Range and If-Range headers.
    String range = request.getHeader(RANGE);
    if (nonNull(range)) {

        // Range header should match format "bytes=n-n,n-n,n-n...". If not, then return 416.
        if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
            log.error("Range header should match format \"bytes=n-n,n-n,n-n...\". If not, then return 416.");
            response.setHeader(CONTENT_RANGE, String.format(BYTES_DINVALID_BYTE_RANGE_FORMAT, length)); // Required in 416.
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }//w w w  . j a  v a2  s. com

        String ifRange = request.getHeader(IF_RANGE);
        if (nonNull(ifRange) && !ifRange.equals(fileName)) {
            try {
                //Assume that the If-Range contains a date
                long ifRangeTime = request.getDateHeader(IF_RANGE); // Throws IAE if invalid.

                if (ifRangeTime == -1 || ifRangeTime + 1000 <= lastModified) {
                    //Our file has been updated, send the full range
                    ranges.add(fullRange);
                }

            } catch (IllegalArgumentException ignore) {
                //Assume that the If-Range contains an ETag
                if (!matches(ifRange, checksum)) {
                    //Our file has been updated, send the full range
                    ranges.add(fullRange);
                }
            }
        }

        // If any valid If-Range header, then process each part of byte range.
        if (ranges.isEmpty()) {
            log.debug("If any valid If-Range header, then process each part of byte range.");
            for (String part : range.substring(6).split(",")) {
                // Assuming a file with length of 100, the following examples returns bytes at:
                // 50-80 (50 to 80), 40- (40 to length=100), -20 (length-20=80 to length=100).
                long start = Range.sublong(part, 0, part.indexOf("-"));
                long end = Range.sublong(part, part.indexOf("-") + 1, part.length());

                if (start == -1) {
                    start = length - end;
                    end = length - 1;
                } else if (end == -1 || end > length - 1) {
                    end = length - 1;
                }

                // Check if Range is syntactically valid. If not, then return 416.
                if (start > end) {
                    log.warn("Check if Range is syntactically valid. If not, then return 416.");
                    response.setHeader(CONTENT_RANGE, String.format(BYTES_DINVALID_BYTE_RANGE_FORMAT, length)); // Required in 416.
                    response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                    return null;
                }

                // Add range.
                ranges.add(new Range(start, end, length));
            }
        }
    }
    return ranges;
}

From source file:ch.entwine.weblounge.common.impl.request.Http11ProtocolHandler.java

/**
 * Method generateResponse.// w  ww  .jav a  2  s  .  c  o m
 * 
 * @param resp
 * @param type
 * @param is
 * @return boolean
 * @throws IOException
 *           if generating the response fails
 */
public static boolean generateResponse(HttpServletResponse resp, Http11ResponseType type, InputStream is)
        throws IOException {

    /* first generate the response headers */
    generateHeaders(resp, type);

    /* adjust the statistics */
    ++stats[STATS_BODY_GENERATED];
    incResponseStats(type.type, bodyStats);

    /* generate the response body */
    try {
        if (resp.isCommitted())
            log.warn("Response is already committed!");
        switch (type.type) {
        case RESPONSE_OK:
            if (!type.isHeaderOnly() && is != null) {
                resp.setBufferSize(BUFFER_SIZE);
                OutputStream os = null;
                try {
                    os = resp.getOutputStream();
                    IOUtils.copy(is, os);
                } catch (IOException e) {
                    if (RequestUtils.isCausedByClient(e))
                        return true;
                } finally {
                    IOUtils.closeQuietly(os);
                }
            }
            break;

        case RESPONSE_PARTIAL_CONTENT:
            if (type.from < 0 || type.to < 0 || type.from > type.to || type.to > type.size) {
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                        "Invalid partial content parameters");
                log.warn("Invalid partial content parameters");
            } else if (!type.isHeaderOnly() && is != null) {
                resp.setBufferSize(BUFFER_SIZE);
                OutputStream os = resp.getOutputStream();
                if (is.skip(type.from) != type.from) {
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                            "Premature end of input stream");
                    log.warn("Premature end of input stream");
                    break;
                }
                try {

                    /* get the temporary buffer for this thread */
                    byte[] tmp = buffer.get();
                    if (tmp == null) {
                        tmp = new byte[BUFFER_SIZE];
                        buffer.set(tmp);
                    }

                    int read = type.to - type.from;
                    int copy = read;
                    int write = 0;

                    read = is.read(tmp);
                    while (copy > 0 && read >= 0) {
                        copy -= read;
                        write = copy > 0 ? read : read + copy;
                        os.write(tmp, 0, write);
                        stats[STATS_BYTES_WRITTEN] += write;
                        read = is.read(tmp);
                    }
                    if (copy > 0) {
                        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                                "Premature end of input stream");
                        log.warn("Premature end of input stream");
                        break;
                    }
                    os.flush();
                    os.close();
                } catch (SocketException e) {
                    log.debug("Request cancelled by client");
                }
            }
            break;

        case RESPONSE_NOT_MODIFIED:
            /* NOTE: we MUST NOT return any content (RFC 2616)!!! */
            break;

        case RESPONSE_PRECONDITION_FAILED:
            if (type.err == null)
                resp.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
            else
                resp.sendError(HttpServletResponse.SC_PRECONDITION_FAILED, type.err);
            break;

        case RESPONSE_REQUESTED_RANGE_NOT_SATISFIABLE:
            if (type.err == null)
                resp.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            else
                resp.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, type.err);
            break;

        case RESPONSE_METHOD_NOT_ALLOWED:
            if (type.err == null)
                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
            else
                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, type.err);
            break;

        case RESPONSE_INTERNAL_SERVER_ERROR:
        default:
            if (type.err == null)
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            else
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, type.err);
        }
    } catch (IOException e) {
        if (e instanceof EOFException) {
            log.debug("Request canceled by client");
            return true;
        }
        ++stats[STATS_ERRORS];
        String message = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
        Throwable cause = e.getCause() != null ? e.getCause() : e;
        log.warn("I/O exception while sending response: {}", message, cause);
        throw e;
    }

    return true;
}

From source file:com.github.zhanhb.ckfinder.download.PathPartial.java

/**
 * Parse the range header./*from   w  w  w.j  a  v a2s  . c o m*/
 *
 * @param request The servlet request we are processing
 * @param response The servlet response we are creating
 * @param attr File attributes
 * @param etag ETag of the entity
 * @return array of ranges
 */
@Nullable
@SuppressWarnings("ReturnOfCollectionOrArrayField")
private Range[] parseRange(HttpServletRequest request, HttpServletResponse response, BasicFileAttributes attr,
        String etag) throws IOException {
    // Checking If-Range
    String headerValue = request.getHeader(HttpHeaders.IF_RANGE);
    if (headerValue != null) {
        long headerValueTime = -1;
        try {
            headerValueTime = request.getDateHeader(HttpHeaders.IF_RANGE);
        } catch (IllegalArgumentException e) {
            // Ignore
        }
        // If the ETag the client gave does not match the entity
        // eTag, then the entire entity is returned.
        if (headerValueTime == -1 && !headerValue.trim().equals(etag)
                || attr.lastModifiedTime().toMillis() > headerValueTime + 1000) {
            // If the timestamp of the entity the client got is older than
            // the last modification date of the entity, the entire entity
            // is returned.
            return FULL;
        }
    }
    long fileLength = attr.size();
    if (fileLength == 0) {
        return FULL;
    }
    // Retrieving the range header (if any is specified
    String rangeHeader = request.getHeader(HttpHeaders.RANGE);
    if (rangeHeader == null) {
        return FULL;
    }
    // bytes is the only range unit supported (and I don't see the point
    // of adding new ones).
    if (!rangeHeader.startsWith("bytes=")) {
        return FULL;
    }
    // List which will contain all the ranges which are successfully
    // parsed.
    List<Range> result = new ArrayList<>(4);
    // Parsing the range list
    // "bytes=".length() = 6
    for (int index, last = 6;; last = index + 1) {
        index = rangeHeader.indexOf(',', last);
        boolean isLast = index == -1;
        final String rangeDefinition = (isLast ? rangeHeader.substring(last)
                : rangeHeader.substring(last, index)).trim();
        final int dashPos = rangeDefinition.indexOf('-');
        if (dashPos == -1) {
            break;
        }
        final Range currentRange = new Range(fileLength);
        try {
            if (dashPos == 0) {
                final long offset = Long.parseLong(rangeDefinition);
                if (offset == 0) { // -0, --0
                    break;
                }
                currentRange.start = Math.max(fileLength + offset, 0);
            } else {
                currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos));
                if (dashPos < rangeDefinition.length() - 1) {
                    currentRange.end = Long
                            .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length()));
                }
            }
        } catch (NumberFormatException e) {
            break;
        }
        if (!currentRange.validate()) {
            break;
        }
        result.add(currentRange);
        if (isLast) {
            int size = result.size();
            if (size == 0) {
                break;
            }
            return result.toArray(new Range[size]);
        }
    }
    response.addHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + fileLength);
    response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
    return null;
}

From source file:hu.api.SivaPlayerVideoServlet.java

private void doAction(HttpServletRequest request, HttpServletResponse response, String requestType)
        throws ServletException, IOException {

    // Check if it's an AJAX request
    this.isAJAXRequest = (request.getParameter("ajax") != null && request.getParameter("ajax").equals("true"));

    // Allow Cross-Origin-Requests
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
    response.setHeader("Access-Control-Max-Age", "1000");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");

    // URL pattern: /videoId
    // Get request parameter from URL and check if it has been set.
    // Show 400 if less or more parameters than allowed.
    String requestedVideo = request.getPathInfo();
    if (requestedVideo == null || requestedVideo.split("/").length < 2
            || requestedVideo.split("/")[1].equals("")) {
        this.sendError(response, HttpServletResponse.SC_BAD_REQUEST,
                "The video folder has to be specified for using this web service.");
        return;//from   w ww .  java2 s  . c o m
    }

    this.persistenceProvider = (IPersistenceProvider) getServletContext().getAttribute("PersistenceProvider");
    this.mailService = (MailService) getServletContext().getAttribute("mailService");
    this.brandingConfiguration = (BrandingConfiguration) getServletContext()
            .getAttribute("brandingConfiguration");

    // Check if it's a watching request
    if (request.getPathInfo().endsWith("/watch.html")) {
        this.providePlayer(request, response);
        return;
    }

    // Check if it's a log request and perform logging if so
    if (request.getPathInfo().endsWith("/log") && requestType.equals("POST")) {
        this.doLogging(request, response);
        return;
    }

    // Check if it's a checkSession request and provide session status if so
    if (requestedVideo.endsWith("/getStats.js")) {
        this.getStats(request, response);
        return;
    }

    // Check if user requests user secret and perform login
    if (request.getPathInfo().endsWith("/getSecret.js") && requestType.equals("POST")) {
        this.provideUserSecret(request, response, requestType);
        return;
    }

    // Check if current session exists and if it is allowed to access this
    // video, stop further execution, if so.
    boolean result = handleAccess(request, response, requestType);
    if (!result) {
        return;
    }

    // Check if it's collaboration request and provide data
    if (request.getPathInfo().endsWith("/getCollaboration.js")) {
        this.provideCollaboration(request, response);
        return;
    }

    // Check if it's a thread creation request
    if (request.getPathInfo().endsWith("/createCollaborationThread.js")) {
        this.createCollaborationThread(request, response);
        return;
    }

    // Check if it's a post creation request
    if (request.getPathInfo().endsWith("/createCollaborationPost.js")) {
        this.createCollaborationPost(request, response);
        return;
    }

    // Check if it's a post activation request
    if (request.getPathInfo().endsWith("/activateCollaborationPost.js")) {
        this.activateCollaborationPost(request, response);
        return;
    }

    // Check if it's a post creation request
    if (request.getPathInfo().endsWith("/deleteCollaborationThread.js")) {
        this.deleteCollaborationThread(request, response);
        return;
    }

    // Check if it's a post creation request
    if (request.getPathInfo().endsWith("/deleteCollaborationPost.js")) {
        this.deleteCollaborationPost(request, response);
        return;
    }

    // Check if it's a checkSession request and provide session status if so
    if (requestedVideo.endsWith("/checkSession.js")) {
        this.provideSessionStatus(request, response);
        return;
    }

    // Decode the file name from the URL and check if file actually exists
    // in
    // file system, send 404 if not
    File file = new File(videoPath, URLDecoder.decode(requestedVideo, "UTF-8"));
    if (!file.exists()) {
        this.sendError(response, HttpServletResponse.SC_NOT_FOUND, "File not found");
        return;
    }

    // Create log entry for file request
    this.logFileRequest(requestedVideo);

    // Check if configuration is requested and do needed preparing and
    // stop standard file preparation
    if (file.getName().equals("export.js")) {
        this.provideConfigFile(request, response, file);
        return;
    }

    // Prepare some variables. The ETag is an unique identifier of the file.
    String fileName = file.getName();
    long length = file.length();
    long lastModified = file.lastModified();
    String eTag = fileName + "_" + length + "_" + lastModified;
    long expires = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME;

    // Validate request headers for caching
    // ---------------------------------------------------

    // If-None-Match header should contain "*" or ETag. If so, then return
    // 304.
    String ifNoneMatch = request.getHeader("If-None-Match");
    if (ifNoneMatch != null && matches(ifNoneMatch, eTag)) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        response.setHeader("ETag", eTag); // Required in 304.
        response.setDateHeader("Expires", expires); // Postpone cache with 1
        // week.
        return;
    }

    // If-Modified-Since header should be greater than LastModified. If so,
    // then return 304.
    // This header is ignored if any If-None-Match header is specified.
    long ifModifiedSince = request.getDateHeader("If-Modified-Since");
    if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModified) {
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        response.setHeader("ETag", eTag); // Required in 304.
        response.setDateHeader("Expires", expires); // Postpone cache with 1
        // week.
        return;
    }

    // Validate request headers for resume
    // ----------------------------------------------------

    // If-Match header should contain "*" or ETag. If not, then return 412.
    String ifMatch = request.getHeader("If-Match");
    if (ifMatch != null && !matches(ifMatch, eTag)) {
        response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
        return;
    }

    // If-Unmodified-Since header should be greater than LastModified. If
    // not, then return 412.
    long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since");
    if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModified) {
        response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
        return;
    }

    // Validate and process range
    // -------------------------------------------------------------

    // Prepare some variables. The full Range represents the complete file.
    Range full = new Range(0, length - 1, length);
    List<Range> ranges = new ArrayList<Range>();

    // Validate and process Range and If-Range headers.
    String range = request.getHeader("Range");
    if (range != null) {

        // Range header should match format "bytes=n-n,n-n,n-n...". If not,
        // then return 416.
        if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
            response.setHeader("Content-Range", "bytes */" + length); // Required
            // in
            // 416.
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return;
        }

        // If-Range header should either match ETag or be greater then
        // LastModified. If not,
        // then return full file.
        String ifRange = request.getHeader("If-Range");
        if (ifRange != null && !ifRange.equals(eTag)) {
            try {
                long ifRangeTime = request.getDateHeader("If-Range"); // Throws
                // IAE
                // if
                // invalid.
                if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) {
                    ranges.add(full);
                }
            } catch (IllegalArgumentException ignore) {
                ranges.add(full);
            }
        }

        // If any valid If-Range header, then process each part of byte
        // range.
        if (ranges.isEmpty()) {
            for (String part : range.substring(6).split(",")) {
                // Assuming a file with length of 100, the following
                // examples returns bytes at:
                // 50-80 (50 to 80), 40- (40 to length=100), -20
                // (length-20=80 to length=100).
                long start = sublong(part, 0, part.indexOf("-"));
                long end = sublong(part, part.indexOf("-") + 1, part.length());

                if (start == -1) {
                    start = length - end;
                    end = length - 1;
                } else if (end == -1 || end > length - 1) {
                    end = length - 1;
                }

                // Check if Range is syntactically valid. If not, then
                // return 416.
                if (start > end) {
                    response.setHeader("Content-Range", "bytes */" + length); // Required
                    // in
                    // 416.
                    response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                    return;
                }

                // Add range.
                ranges.add(new Range(start, end, length));
            }
        }
    }

    // Prepare and initialize response
    // --------------------------------------------------------

    // Get content type by file name and set default GZIP support and
    // content disposition.
    String contentType = getServletContext().getMimeType(fileName);
    boolean acceptsGzip = false;
    String disposition = "inline";

    // If content type is unknown, then set the default value.
    // For all content types, see:
    // http://www.w3schools.com/media/media_mimeref.asp
    // To add new content types, add new mime-mapping entry in web.xml.
    if (contentType == null) {
        contentType = "application/octet-stream";
    }

    // If content type is text, then determine whether GZIP content encoding
    // is supported by
    // the browser and expand content type with the one and right character
    // encoding.
    if (contentType.startsWith("text")) {
        String acceptEncoding = request.getHeader("Accept-Encoding");
        acceptsGzip = acceptEncoding != null && accepts(acceptEncoding, "gzip");
        contentType += ";charset=UTF-8";
    }

    // Else, expect for images, determine content disposition. If content
    // type is supported by
    // the browser, then set to inline, else attachment which will pop a
    // 'save as' dialogue.
    else if (!contentType.startsWith("image")) {
        String accept = request.getHeader("Accept");
        disposition = accept != null && accepts(accept, contentType) ? "inline" : "attachment";
    }

    // Initialize response.
    response.reset();
    response.setBufferSize(DEFAULT_BUFFER_SIZE);
    response.setHeader("Content-Disposition", disposition + ";filename=\"" + fileName + "\"");
    response.setHeader("Accept-Ranges", "bytes");
    response.setHeader("ETag", eTag);
    response.setDateHeader("Last-Modified", lastModified);
    response.setDateHeader("Expires", expires);

    // Send requested file (part(s)) to client
    // ------------------------------------------------

    // Prepare streams.
    RandomAccessFile input = null;
    OutputStream output = null;

    try {
        // Open streams.
        input = new RandomAccessFile(file, "r");
        output = response.getOutputStream();

        if (ranges.isEmpty() || ranges.get(0) == full) {

            // Return full file.
            Range r = full;
            response.setContentType(contentType);
            response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);

            if (requestType.equals("GET")) {
                if (acceptsGzip) {
                    // The browser accepts GZIP, so GZIP the content.
                    response.setHeader("Content-Encoding", "gzip");
                    output = new GZIPOutputStream(output, DEFAULT_BUFFER_SIZE);
                } else {
                    // Content length is not directly predictable in case of
                    // GZIP.
                    // So only add it if there is no means of GZIP, else
                    // browser will hang.
                    response.setHeader("Content-Length", String.valueOf(r.length));
                }

                // Copy full range.
                copy(input, output, r.start, r.length);
            }

        } else if (ranges.size() == 1) {

            // Return single part of file.
            Range r = ranges.get(0);
            response.setContentType(contentType);
            response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
            response.setHeader("Content-Length", String.valueOf(r.length));
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.

            if (requestType.equals("GET")) {
                // Copy single part range.
                copy(input, output, r.start, r.length);
            }

        } else {

            // Return multiple parts of file.
            response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.

            if (requestType.equals("GET")) {
                // Cast back to ServletOutputStream to get the easy println
                // methods.
                ServletOutputStream sos = (ServletOutputStream) output;

                // Copy multi part range.
                for (Range r : ranges) {
                    // Add multipart boundary and header fields for every
                    // range.
                    sos.println();
                    sos.println("--" + MULTIPART_BOUNDARY);
                    sos.println("Content-Type: " + contentType);
                    sos.println("Content-Range: bytes " + r.start + "-" + r.end + "/" + r.total);

                    // Copy single part range of multi part range.
                    copy(input, output, r.start, r.length);
                }

                // End with multipart boundary.
                sos.println();
                sos.println("--" + MULTIPART_BOUNDARY + "--");
            }
        }
    } finally {
        // Gently close streams.
        close(output);
        close(input);
    }
}

From source file:com.liferay.sync.servlet.DownloadServlet.java

protected void sendFileWithRangeHeader(HttpServletRequest request, HttpServletResponse response,
        String fileName, InputStream inputStream, long contentLength, String contentType) throws IOException {

    if (_log.isDebugEnabled()) {
        _log.debug("Accepting ranges for the file " + fileName);
    }// w w w. j  a  v a 2 s  . c  o  m

    response.setHeader(HttpHeaders.ACCEPT_RANGES, HttpHeaders.ACCEPT_RANGES_BYTES_VALUE);

    List<Range> ranges = null;

    try {
        ranges = ServletResponseUtil.getRanges(request, response, contentLength);
    } catch (IOException ioe) {
        if (_log.isErrorEnabled()) {
            _log.error(ioe);
        }

        response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + contentLength);

        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);

        return;
    }

    if ((ranges == null) || ranges.isEmpty()) {
        ServletResponseUtil.sendFile(request, response, fileName, inputStream, contentLength, contentType);
    } else {
        if (_log.isDebugEnabled()) {
            _log.debug("Request has range header " + request.getHeader(HttpHeaders.RANGE));
        }

        ServletResponseUtil.write(request, response, fileName, ranges, inputStream, contentLength, contentType);
    }
}

From source file:com.meltmedia.cadmium.servlets.BasicFileServlet.java

/**
 * Sets the appropriate response headers and error status for bad ranges
 * /* www.  j a  v  a2s . c  o  m*/
 * @param context
 * @throws IOException
 */
public static void invalidRanges(FileRequestContext context) throws IOException {
    context.response.setHeader(CONTENT_RANGE_HEADER, "*/" + context.file.length());
    context.response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
}