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.mycore.common.content.util.MCRServletContentHelper.java

/**
 * Parses and validates the range header.
 * This method ensures that all ranges are in ascending order and non-overlapping, so we can use a single
 * InputStream.//  w w w  .  j  a v a2  s  .c  om
 */
private static ArrayList<Range> parseRange(final HttpServletRequest request, final HttpServletResponse response,
        final MCRContent content) throws IOException {

    // Checking if range is still valid (lastModified)
    final String headerValue = request.getHeader("If-Range");

    if (headerValue != null) {
        long headerValueTime = -1L;
        try {
            headerValueTime = request.getDateHeader("If-Range");
        } catch (final IllegalArgumentException e) {
            // Ignore
        }

        final String eTag = content.getETag();
        final long lastModified = content.lastModified();

        if (headerValueTime == -1L) {
            // If the content changed, the complete content is served.
            if (!eTag.equals(headerValue.trim())) {
                return FULL;
            }
        } else {
            //add one second buffer to check if the content was modified.
            if (lastModified > headerValueTime + 1000) {
                return FULL;
            }
        }

    }

    final long fileLength = content.length();
    if (fileLength <= 0) {
        return null;
    }

    String rangeHeader = request.getHeader("Range");
    if (rangeHeader == null) {
        return null;
    }

    // We operate on byte level only
    String rangeUnit = "bytes";
    if (!rangeHeader.startsWith(rangeUnit)) {
        response.addHeader("Content-Range", "bytes */" + fileLength);
        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
        return null;
    }

    rangeHeader = rangeHeader.substring(rangeUnit.length() + 1);

    final ArrayList<Range> result = new ArrayList<>();
    final StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ",");

    // Parsing the range list
    long lastByte = 0;
    while (commaTokenizer.hasMoreTokens()) {
        final String rangeDefinition = commaTokenizer.nextToken().trim();

        final Range currentRange = new Range();
        currentRange.length = fileLength;

        final int dashPos = rangeDefinition.indexOf('-');

        if (dashPos == -1) {
            response.addHeader("Content-Range", "bytes */" + fileLength);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }

        if (dashPos == 0) {

            try {
                //offset is negative
                final long offset = Long.parseLong(rangeDefinition);
                currentRange.start = fileLength + offset;
                currentRange.end = fileLength - 1;
            } catch (final NumberFormatException e) {
                response.addHeader("Content-Range", "bytes */" + fileLength);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        } else {

            try {
                currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos));
                if (dashPos < rangeDefinition.length() - 1) {
                    currentRange.end = Long
                            .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length()));
                } else {
                    currentRange.end = fileLength - 1;
                }
            } catch (final NumberFormatException e) {
                response.addHeader("Content-Range", "bytes */" + fileLength);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        }

        if (!currentRange.validate() || lastByte > currentRange.start) {
            response.addHeader("Content-Range", "bytes */" + fileLength);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }
        lastByte = currentRange.end;
        result.add(currentRange);
    }
    return result;
}

From source file:org.openhab.ui.cometvisu.internal.servlet.CometVisuServlet.java

/**
 * Process the actual request./*from   ww w  .ja va2  s  .  c o m*/
 *
 * @param request
 *            The request to be processed.
 * @param response
 *            The response to be created.
 * @param content
 *            Whether the request body should be written (GET) or not
 *            (HEAD).
 * @throws IOException
 *             If something fails at I/O level.
 *
 * @author BalusC
 * @link
 *       http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and
 *       .html
 */
private void processStaticRequest(File file, HttpServletRequest request, HttpServletResponse response,
        boolean content) throws IOException {
    // Validate the requested file
    // ------------------------------------------------------------
    if (file == null) {
        // Get requested file by path info.
        String requestedFile = request.getPathInfo();

        // Check if file is actually supplied to the request URL.
        if (requestedFile == null) {
            // Do your thing if the file is not supplied to the request URL.
            // Throw an exception, or send 404, or show default/warning
            // page, or
            // just ignore it.
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        // URL-decode the file name (might contain spaces and on) and
        // prepare
        // file object.
        file = new File(rootFolder, URLDecoder.decode(requestedFile, "UTF-8"));
    }
    if (file.equals(rootFolder) || (file.exists() && file.isDirectory())) {
        file = new File(file, "index.html");
    }

    // Check if file actually exists in filesystem.
    if (!file.exists()) {
        // show installation hints if the CometVisu-Clients main index.html is requested but cannot be found
        if (file.getParentFile().equals(rootFolder)
                && (file.getName().equalsIgnoreCase("index.html") || file.getName().length() == 0)) {
            // looking for CometVisu clients index.html file
            String path = null;
            File folder = file.isDirectory() ? file : file.getParentFile();
            if (folder.exists()) {
                File index = ClientInstaller.findClientRoot(folder, "index.html");
                path = index.exists() ? index.getPath().replaceFirst(rootFolder.getPath() + "/", "") : null;
            }
            if (path != null) {
                // forward to position
                response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
                response.setHeader("Location", path + "?" + request.getQueryString());
            } else {
                showInstallationHint(request, response);
            }
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
        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";
    }

    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 (content) {
                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 (content) {
                // 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 (content) {
                // 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:org.apache.catalina.servlets.DefaultServlet.java

/**
 * Parse the range header./*from   www . j  a v a  2  s  .  c  o  m*/
 *
 * @param request      The servlet request we are processing
 * @param response     The servlet response we are creating
 * @param resourceInfo Description of the Parameter
 * @return Vector of ranges
 * @throws IOException Description of the Exception
 */
protected Vector parseRange(HttpServletRequest request, HttpServletResponse response, ResourceInfo resourceInfo)
        throws IOException {

    // Checking If-Range
    String headerValue = request.getHeader("If-Range");

    if (headerValue != null) {

        long headerValueTime = (-1L);
        try {
            headerValueTime = request.getDateHeader("If-Range");
        } catch (Exception e) {
            ;
        }

        String eTag = getETag(resourceInfo);
        long lastModified = resourceInfo.date;

        if (headerValueTime == (-1L)) {

            // If the ETag the client gave does not match the entity
            // etag, then the entire entity is returned.
            if (!eTag.equals(headerValue.trim())) {
                return null;
            }
        } else {

            // If the timestamp of the entity the client got is older than
            // the last modification date of the entity, the entire entity
            // is returned.
            if (lastModified > (headerValueTime + 1000)) {
                return null;
            }
        }

    }

    long fileLength = resourceInfo.length;

    if (fileLength == 0) {
        return null;
    }

    // Retrieving the range header (if any is specified
    String rangeHeader = request.getHeader("Range");

    if (rangeHeader == null) {
        return null;
    }
    // bytes is the only range unit supported (and I don't see the point
    // of adding new ones).
    if (!rangeHeader.startsWith("bytes")) {
        response.addHeader("Content-Range", "bytes */" + fileLength);
        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
        return null;
    }

    rangeHeader = rangeHeader.substring(6);

    // Vector which will contain all the ranges which are successfully
    // parsed.
    Vector result = new Vector();
    StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ",");

    // Parsing the range list
    while (commaTokenizer.hasMoreTokens()) {
        String rangeDefinition = commaTokenizer.nextToken().trim();

        Range currentRange = new Range();
        currentRange.length = fileLength;

        int dashPos = rangeDefinition.indexOf('-');

        if (dashPos == -1) {
            response.addHeader("Content-Range", "bytes */" + fileLength);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }

        if (dashPos == 0) {

            try {
                long offset = Long.parseLong(rangeDefinition);
                currentRange.start = fileLength + offset;
                currentRange.end = fileLength - 1;
            } catch (NumberFormatException e) {
                response.addHeader("Content-Range", "bytes */" + fileLength);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        } else {

            try {
                currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos));
                if (dashPos < rangeDefinition.length() - 1) {
                    currentRange.end = Long
                            .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length()));
                } else {
                    currentRange.end = fileLength - 1;
                }
            } catch (NumberFormatException e) {
                response.addHeader("Content-Range", "bytes */" + fileLength);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        }

        if (!currentRange.validate()) {
            response.addHeader("Content-Range", "bytes */" + fileLength);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }

        result.addElement(currentRange);
    }

    return result;
}

From source file:org.opencms.webdav.CmsWebdavServlet.java

/**
 * Parse the range header.<p>/*from  w  w w  .j  av  a2s .c o m*/
 *
 * @param request the servlet request we are processing
 * @param response the servlet response we are creating
 * @param item the WebdavItem with the information
 * 
 * @return Vector of ranges
 */
protected ArrayList<CmsWebdavRange> parseRange(HttpServletRequest request, HttpServletResponse response,
        I_CmsRepositoryItem item) {

    // Checking If-Range
    String headerValue = request.getHeader(HEADER_IFRANGE);

    if (headerValue != null) {

        long headerValueTime = (-1L);
        try {
            headerValueTime = request.getDateHeader(HEADER_IFRANGE);
        } catch (Exception e) {
            // noop
        }

        String eTag = getETag(item);
        long lastModified = item.getLastModifiedDate();

        if (headerValueTime == (-1L)) {

            // If the ETag the client gave does not match the entity
            // etag, then the entire entity is returned.
            if (!eTag.equals(headerValue.trim())) {
                return FULL_RANGE;
            }

        } else {

            // If the timestamp of the entity the client got is older than
            // the last modification date of the entity, the entire entity
            // is returned.
            if (lastModified > (headerValueTime + 1000)) {
                return FULL_RANGE;
            }
        }
    }

    long fileLength = item.getContentLength();

    if (fileLength == 0) {
        return null;
    }

    // Retrieving the range header (if any is specified
    String rangeHeader = request.getHeader(HEADER_RANGE);

    if (rangeHeader == null) {
        return null;
    }

    // bytes is the only range unit supported (and I don't see the point
    // of adding new ones).
    if (!rangeHeader.startsWith("bytes")) {
        response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength);
        response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
        return null;
    }

    rangeHeader = rangeHeader.substring(6);

    // Vector which will contain all the ranges which are successfully parsed.
    ArrayList<CmsWebdavRange> result = new ArrayList<CmsWebdavRange>();
    StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ",");

    // Parsing the range list
    while (commaTokenizer.hasMoreTokens()) {
        String rangeDefinition = commaTokenizer.nextToken().trim();

        CmsWebdavRange currentRange = new CmsWebdavRange();
        currentRange.setLength(fileLength);

        int dashPos = rangeDefinition.indexOf('-');

        if (dashPos == -1) {
            response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength);
            response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }

        if (dashPos == 0) {

            try {
                long offset = Long.parseLong(rangeDefinition);
                currentRange.setStart(fileLength + offset);
                currentRange.setEnd(fileLength - 1);
            } catch (NumberFormatException e) {
                response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength);
                response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        } else {

            try {
                currentRange.setStart(Long.parseLong(rangeDefinition.substring(0, dashPos)));
                if (dashPos < (rangeDefinition.length() - 1)) {
                    currentRange.setEnd(
                            Long.parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length())));
                } else {
                    currentRange.setEnd(fileLength - 1);
                }
            } catch (NumberFormatException e) {
                response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength);
                response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        }

        if (!currentRange.validate()) {
            response.addHeader(HEADER_CONTENTRANGE, "bytes */" + fileLength);
            response.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }

        result.add(currentRange);
    }

    return result;
}

From source file:org.gss_project.gss.server.rest.Webdav.java

/**
 * Parse the range header.//from w  ww  .j  a  v  a2s  .com
 *
 * @param request The servlet request we are processing
 * @param response The servlet response we are creating
 * @param file
 * @param oldBody the old version of the file, if requested
 * @return Vector of ranges
 * @throws IOException
 */
protected ArrayList parseRange(HttpServletRequest request, HttpServletResponse response, FileHeader file,
        FileBody oldBody) throws IOException {
    // Checking If-Range
    String headerValue = request.getHeader("If-Range");
    if (headerValue != null) {
        long headerValueTime = -1L;
        try {
            headerValueTime = request.getDateHeader("If-Range");
        } catch (IllegalArgumentException e) {
            // Do nothing.
        }

        String eTag = getETag(file, oldBody);
        long lastModified = oldBody == null ? file.getAuditInfo().getModificationDate().getTime()
                : oldBody.getAuditInfo().getModificationDate().getTime();

        if (headerValueTime == -1L) {
            // If the ETag the client gave does not match the entity
            // etag, then the entire entity is returned.
            if (!eTag.equals(headerValue.trim()))
                return FULL;
        } else
        // If the timestamp of the entity the client got is older than
        // the last modification date of the entity, the entire entity
        // is returned.
        if (lastModified > headerValueTime + 1000)
            return FULL;
    }

    long fileLength = oldBody == null ? file.getCurrentBody().getFileSize() : oldBody.getFileSize();
    if (fileLength == 0)
        return null;

    // Retrieving the range header (if any is specified).
    String rangeHeader = request.getHeader("Range");

    if (rangeHeader == null)
        return null;
    // bytes is the only range unit supported (and I don't see the point
    // of adding new ones).
    if (!rangeHeader.startsWith("bytes")) {
        response.addHeader("Content-Range", "bytes */" + fileLength);
        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
        return null;
    }

    rangeHeader = rangeHeader.substring(6);

    // Vector that will contain all the ranges which are successfully
    // parsed.
    ArrayList<Range> result = new ArrayList<Range>();
    StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ",");
    // Parsing the range list
    while (commaTokenizer.hasMoreTokens()) {
        String rangeDefinition = commaTokenizer.nextToken().trim();

        Range currentRange = new Range();
        currentRange.length = fileLength;

        int dashPos = rangeDefinition.indexOf('-');

        if (dashPos == -1) {
            response.addHeader("Content-Range", "bytes */" + fileLength);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }

        if (dashPos == 0)
            try {
                long offset = Long.parseLong(rangeDefinition);
                currentRange.start = fileLength + offset;
                currentRange.end = fileLength - 1;
            } catch (NumberFormatException e) {
                response.addHeader("Content-Range", "bytes */" + fileLength);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }
        else
            try {
                currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos));
                if (dashPos < rangeDefinition.length() - 1)
                    currentRange.end = Long
                            .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length()));
                else
                    currentRange.end = fileLength - 1;
            } catch (NumberFormatException e) {
                response.addHeader("Content-Range", "bytes */" + fileLength);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        if (!currentRange.validate()) {
            response.addHeader("Content-Range", "bytes */" + fileLength);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }
        result.add(currentRange);
    }
    return result;
}

From source file:de.innovationgate.wgpublisher.WGPDispatcher.java

/**
 * writes the given data to the response based on response.getContentType()
 * either reader/writer (for textual content) or binary streams are used
 * /*from   w w w. j ava 2s  .  com*/
 * @param data
 *            - the data as inputstream to write - implicit closed after
 *            method call
 * @param request
 * @param response
 * @param characterEncoding
 *            - encoding to use when reading character based from given
 *            data, if null platform encoding is used
 * @throws IOException
 * @throws HttpErrorException
 */
private void writeData(DataSource data, HttpServletRequest request, HttpServletResponse response,
        String characterEncoding, long size, String sourceHint, boolean allowRequestRanges)
        throws IOException, HttpErrorException {

    // Parse accept ranges if requested
    List<AcceptRange> ranges = new ArrayList<AcceptRange>();
    String rangeHeader = request.getHeader("Range");
    if (rangeHeader != null && allowRequestRanges && size > 0) {
        if (rangeHeader.startsWith("bytes=")) {
            rangeHeader = rangeHeader.substring("bytes=".length());
            String[] subranges = rangeHeader.split("\\s*,\\s*");
            for (String r : subranges) {
                Matcher matcher = ACCEPT_RANGE_PATTERN.matcher(r);
                if (matcher.matches()) {
                    String from = matcher.group(1);
                    String to = matcher.group(2);
                    AcceptRange newRange;

                    try {
                        newRange = new AcceptRange(from != null ? Integer.parseInt(from) : -1,
                                to != null ? Integer.parseInt(to) : -1);
                        if (newRange.from == -1) {
                            newRange.from = size - newRange.to;
                            newRange.to = size - 1;
                        } else if (newRange.to == -1) {
                            newRange.to = size - 1;
                        }
                    } catch (NumberFormatException e) {
                        response.addHeader("Content-Range", "bytes */" + size);
                        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                        return;
                    }

                    if ((newRange.from == -1 && newRange.to == -1) || newRange.to > size) {
                        response.addHeader("Content-Range", "bytes */" + size);
                        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                        return;
                    }
                    ranges.add(newRange);
                } else {
                    response.addHeader("Content-Range", "bytes */" + size);
                    response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                    return;
                }
            }
        } else {
            response.addHeader("Content-Range", "bytes */" + size);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return;
        }
    }

    if (ranges.isEmpty()) {
        // We can only set the raw length on binary resources bc.
        // transcoding textual response can change the size
        if (isBinary(request, response) && size > 0) {
            response.setContentLength((new Long(size)).intValue());
        }

        if (!"HEAD".equalsIgnoreCase(request.getMethod())) {
            writeWholeData(data, request, response, characterEncoding, sourceHint);
        }

    } else {
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
        if (ranges.size() == 1) {
            AcceptRange r = ranges.get(0);
            response.addHeader("Content-Range", "bytes " + r.from + "-" + r.to + "/" + size);
            response.setContentLength((new Long(r.to - r.from + 1)).intValue());
        } else {
            response.setContentType("multipart/byteranges; boundary=" + BYTERANGE_BOUNDARY);
        }

        if (!"HEAD".equalsIgnoreCase(request.getMethod())) {
            writeRangesData(data, ranges, response, sourceHint, size);
        }
    }

}

From source file:org.sakaiproject.content.impl.BaseContentService.java

/**
 * Parse the range header.//w  w w. java  2s.  com
 *
 * @param request The servlet request we are processing
 * @param response The servlet response we are creating
 * @return Vector of ranges
 */
protected ArrayList<Range> parseRange(HttpServletRequest request, HttpServletResponse response, long fileLength)
        throws IOException {

    /* Commented out pending implementation of last-modified / if-modified.
     * See http://jira.sakaiproject.org/jira/browse/SAK-3916
            
     // Checking If-Range
            
    String headerValue = request.getHeader("If-Range");
            
     if (headerValue != null) {
            
    long headerValueTime = (-1L);
    try {
        headerValueTime = request.getDateHeader("If-Range");
    } catch (Exception e) {
        ;
    }
            
    String eTag = getETag(resourceAttributes);
    long lastModified = resourceAttributes.getLastModified();
            
    if (headerValueTime == (-1L)) {
            
        // If the ETag the client gave does not match the entity
        // etag, then the entire entity is returned.
        if (!eTag.equals(headerValue.trim()))
            return FULL;
            
    } else {
            
        // If the timestamp of the entity the client got is older than
        // the last modification date of the entity, the entire entity
        // is returned.
        if (lastModified > (headerValueTime + 1000))
            return FULL;
            
    }
            
     }
             
    */

    if (fileLength == 0)
        return null;

    // Retrieving the range header (if any is specified
    String rangeHeader = request.getHeader("Range");

    if (rangeHeader == null)
        return null;
    // bytes is the only range unit supported (and I don't see the point
    // of adding new ones).
    if (!rangeHeader.startsWith("bytes")) {
        response.addHeader("Content-Range", "bytes */" + fileLength);
        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
        return null;
    }

    rangeHeader = rangeHeader.substring(6);

    // Vector which will contain all the ranges which are successfully
    // parsed.
    ArrayList result = new ArrayList();
    StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ",");

    // Parsing the range list
    while (commaTokenizer.hasMoreTokens()) {
        String rangeDefinition = commaTokenizer.nextToken().trim();

        Range currentRange = new Range();
        currentRange.length = fileLength;

        int dashPos = rangeDefinition.indexOf('-');

        if (dashPos == -1) {
            response.addHeader("Content-Range", "bytes */" + fileLength);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }

        if (dashPos == 0) {

            try {
                long offset = Long.parseLong(rangeDefinition);
                currentRange.start = fileLength + offset;
                currentRange.end = fileLength - 1;
            } catch (NumberFormatException e) {
                response.addHeader("Content-Range", "bytes */" + fileLength);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        } else {

            try {
                currentRange.start = Long.parseLong(rangeDefinition.substring(0, dashPos));
                if (dashPos < rangeDefinition.length() - 1)
                    currentRange.end = Long
                            .parseLong(rangeDefinition.substring(dashPos + 1, rangeDefinition.length()));
                else
                    currentRange.end = fileLength - 1;
            } catch (NumberFormatException e) {
                response.addHeader("Content-Range", "bytes */" + fileLength);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return null;
            }

        }

        if (!currentRange.validate()) {
            response.addHeader("Content-Range", "bytes */" + fileLength);
            response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            return null;
        }

        result.add(currentRange);
    }

    return result;
}