Example usage for javax.servlet.http HttpServletResponse SC_PARTIAL_CONTENT

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

Introduction

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

Prototype

int SC_PARTIAL_CONTENT

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

Click Source Link

Document

Status code (206) indicating that the server has fulfilled the partial GET request for the resource.

Usage

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

/**
 * Process the actual request./*from   w  w w. ja  v  a  2 s.c  om*/
 *
 * @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"));
    }
    // Check if file actually exists in filesystem.
    if (!file.exists()) {
        // Do your thing if the file appears to be non-existing.
        // Throw an exception, or send 404, or show default/warning page, or
        // just ignore it.
        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";
    }

    // 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 (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.openhab.ui.cometvisu.internal.servlet.CometVisuServlet.java

/**
 * Process the actual request./*from ww  w  .j a v a  2 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.sakaiproject.lessonbuildertool.service.LessonBuilderAccessService.java

public HttpAccess getHttpAccess() {
    return new HttpAccess() {

        public void handleAccess(HttpServletRequest req, HttpServletResponse res, Reference ref,
                Collection copyrightAcceptedRefs) throws EntityPermissionException, EntityNotDefinedException,
                EntityAccessOverloadException, EntityCopyrightException {

            // preauthorized by encrypted key
            boolean isAuth = false;

            // if the id is null, the request was for just ".../content"
            String refId = ref.getId();
            if (refId == null) {
                refId = "";
            }//from   w  w w .  j  a v a  2  s.c o  m

            if (!refId.startsWith("/item")) {
                throw new EntityNotDefinedException(ref.getReference());
            }

            String itemString = refId.substring("/item/".length());
            // string is of form /item/NNN/url. get the number
            int i = itemString.indexOf("/");
            if (i < 0) {
                throw new EntityNotDefinedException(ref.getReference());
            }

            // get session. The problem here is that some multimedia tools don't reliably
            // pass JSESSIONID

            String sessionParam = req.getParameter("lb.session");

            if (sessionParam != null) {
                try {
                    Cipher sessionCipher = Cipher.getInstance("Blowfish");
                    sessionCipher.init(Cipher.DECRYPT_MODE, sessionKey);
                    byte[] sessionBytes = DatatypeConverter.parseHexBinary(sessionParam);
                    sessionBytes = sessionCipher.doFinal(sessionBytes);
                    String sessionString = new String(sessionBytes);
                    int j = sessionString.indexOf(":");
                    String sessionId = sessionString.substring(0, j);
                    String url = sessionString.substring(j + 1);

                    UsageSession s = UsageSessionService.getSession(sessionId);
                    if (s == null || s.isClosed() || url == null || !url.equals(refId)) {
                        throw new EntityPermissionException(sessionManager.getCurrentSessionUserId(),
                                ContentHostingService.AUTH_RESOURCE_READ, ref.getReference());
                    } else {
                        isAuth = true;
                    }

                } catch (Exception e) {
                    System.out.println("unable to decode lb.session " + e);
                }
            }

            // basically there are two checks to be done: is the item accessible in Lessons,
            // and is the underlying resource accessible in Sakai.
            // This code really does check both. Sort of. 
            // 1) it checks accessibility to the containing page by seeing if it has been visited.
            //  This is stricter than necessary, but there's no obvious reason to let people use this
            //  who aren't following an actual URL we gave them.
            // 2) it checks group access as part of the normal resource permission check. Sakai
            //  should sync the two. We actually don't check it for items in student home directories,
            //  as far as I can tell
            // 3) it checks availability (prerequisites) by calling the code from SimplePageBean
            // We could rewrite this with the new LessonsAccess methods, but since we have to do
            // resource permission checking also, and there's some duplication, it doesn't seem worth
            // rewriting this code. What I've done is review it to make sure it does the same thing.

            String id = itemString.substring(i);
            itemString = itemString.substring(0, i);

            boolean pushedAdvisor = false;

            try {
                securityService.pushAdvisor(allowReadAdvisor);

                pushedAdvisor = true;

                Long itemId = 0L;
                try {
                    itemId = (Long) Long.parseLong(itemString);
                } catch (Exception e) {
                    throw new EntityNotDefinedException(ref.getReference());
                }

                // say we've read this
                if (itemId != 0L)
                    track(itemId.longValue(), sessionManager.getCurrentSessionUserId());

                // code here is also in simplePageBean.isItemVisible. change it there
                // too if you change this logic

                SimplePageItem item = simplePageToolDao.findItem(itemId.longValue());
                SimplePage currentPage = simplePageToolDao.getPage(item.getPageId());
                String owner = currentPage.getOwner(); // if student content
                String group = currentPage.getGroup(); // if student content
                if (group != null)
                    group = "/site/" + currentPage.getSiteId() + "/group/" + group;
                String currentSiteId = currentPage.getSiteId();

                // first let's make sure the user is allowed to access
                // the containing page

                if (!isAuth && !canReadPage(currentSiteId)) {
                    throw new EntityPermissionException(sessionManager.getCurrentSessionUserId(),
                            ContentHostingService.AUTH_RESOURCE_READ, ref.getReference());
                }

                // If the resource is the actual one in the item, or
                // it is in the containing folder, then do lesson builder checking.
                // otherwise do normal resource checking

                if (!isAuth) {

                    boolean useLb = false;

                    // I've seen sakai id's with //, not sure why. they work but will mess up the comparison
                    String itemResource = item.getSakaiId().replace("//", "/");

                    // only use lb security if the user has visited the page
                    // this handles the various page release issues, although
                    // it's not quite as flexible as the real code. But I don't
                    // see any reason to help the user follow URLs that they can't
                    // legitimately have seen.

                    if (simplePageToolDao.isPageVisited(item.getPageId(),
                            sessionManager.getCurrentSessionUserId(), owner)) {
                        if (id.equals(itemResource))
                            useLb = true;
                        else {
                            // not exact, but see if it's in the containing folder
                            int endFolder = itemResource.lastIndexOf("/");
                            if (endFolder > 0) {
                                String folder = itemResource.substring(0, endFolder + 1);
                                if (id.startsWith(folder))
                                    useLb = true;
                            }
                        }
                    }

                    if (useLb) {
                        // key into access cache
                        String accessKey = itemString + ":" + sessionManager.getCurrentSessionUserId();
                        // special access if we have a student site and item is in worksite of one of the students
                        // Normally we require that the person doing the access be able to see the file, but in
                        // that specific case we allow the access. Note that in order to get a sakaiid pointing
                        // into the user's space, the person editing the page must have been able to read the file.
                        // this allows a user in your group to share any of your resources that he can see.
                        String usersite = null;
                        if (owner != null && group != null && id.startsWith("/user/")) {
                            String username = id.substring(6);
                            int slash = username.indexOf("/");
                            if (slash > 0)
                                usersite = username.substring(0, slash);
                            // normally it is /user/EID, so convert to userid
                            try {
                                usersite = UserDirectoryService.getUserId(usersite);
                            } catch (Exception e) {
                            }
                            ;
                            String itemcreator = item.getAttribute("addedby");
                            // suppose a member of the group adds a resource from another member of
                            // the group. (This will only work if they have read access to it.)
                            // We don't want to gimick access in that case. I think if you
                            // add your own item, you've given consent. But not if someone else does.
                            // itemcreator == null is for items added before this patch. I'm going to
                            // continue to allow access for them, to avoid breaking existing content.
                            if (usersite != null && itemcreator != null && !usersite.equals(itemcreator))
                                usersite = null;
                        }

                        // code here is also in simplePageBean.isItemVisible. change it there
                        // too if you change this logic

                        // for a student page, if it's in one of the groups' worksites, allow it
                        // The assumption is that only one of those people can put content in the
                        // page, and then only if the can see it.

                        if (owner != null && usersite != null
                                && authzGroupService.getUserRole(usersite, group) != null) {
                            // OK
                        } else if (owner != null && group == null && id.startsWith("/user/" + owner)) {
                            // OK
                        } else {
                            // do normal checking for other content
                            if (pushedAdvisor) {
                                securityService.popAdvisor();
                                pushedAdvisor = false;
                            }
                            // our version of allowget does not check hidden but does everything else
                            // if it's a student page, however use the normal check so students can't
                            // use this to bypass release control
                            if (owner == null && !allowGetResource(id, currentSiteId)
                                    || owner != null && !contentHostingService.allowGetResource(id)) {
                                throw new EntityPermissionException(sessionManager.getCurrentSessionUserId(),
                                        ContentHostingService.AUTH_RESOURCE_READ, ref.getReference());
                            }

                            securityService.pushAdvisor(allowReadAdvisor);
                            pushedAdvisor = true;

                        }

                        // now enforce LB access restrictions if any
                        if (item != null && item.isPrerequisite()
                                && !"true".equals((String) accessCache.get(accessKey))) {
                            // computing requirements is so messy that it's worth
                            // instantiating
                            // a SimplePageBean to do it. Otherwise we have to duplicate
                            // lots of
                            // code that changes. And we want it to be a transient bean
                            // because there are
                            // caches that we aren't trying to manage in the long term
                            // but don't do this unless the item needs checking

                            if (!canSeeAll(currentPage.getSiteId())) {
                                SimplePageBean simplePageBean = new SimplePageBean();
                                simplePageBean.setMessageLocator(messageLocator);
                                simplePageBean.setToolManager(toolManager);
                                simplePageBean.setSecurityService(securityService);
                                simplePageBean.setSessionManager(sessionManager);
                                simplePageBean.setSiteService(siteService);
                                simplePageBean.setContentHostingService(contentHostingService);
                                simplePageBean.setSimplePageToolDao(simplePageToolDao);
                                simplePageBean.setForumEntity(forumEntity);
                                simplePageBean.setQuizEntity(quizEntity);
                                simplePageBean.setAssignmentEntity(assignmentEntity);
                                simplePageBean.setBltiEntity(bltiEntity);
                                simplePageBean.setGradebookIfc(gradebookIfc);
                                simplePageBean.setMemoryService(memoryService);
                                simplePageBean.setCurrentSiteId(currentPage.getSiteId());
                                simplePageBean.setCurrentPage(currentPage);
                                simplePageBean.setCurrentPageId(currentPage.getPageId());
                                simplePageBean.init();

                                if (!simplePageBean.isItemAvailable(item, item.getPageId())) {
                                    throw new EntityPermissionException(null, null, null);
                                }
                            }
                            accessCache.put(accessKey, "true");

                        }
                    } else {

                        // normal security. no reason to use advisor
                        if (pushedAdvisor)
                            securityService.popAdvisor();
                        pushedAdvisor = false;

                        // not uselb -- their allowget, not ours. theirs checks hidden
                        if (!contentHostingService.allowGetResource(id)) {
                            throw new EntityPermissionException(sessionManager.getCurrentSessionUserId(),
                                    ContentHostingService.AUTH_RESOURCE_READ, ref.getReference());
                        }
                    }

                }

                // access checks are OK, get the thing

                // first see if it's not in resources, i.e.
                // if it doesn't start with /access/content it's something odd. redirect to it.
                // probably resources access control won't apply to it
                String url = contentHostingService.getUrl(id);
                // https://heidelberg.rutgers.edu/access/citation/content/group/24da8519-08c2-4c8c-baeb-8abdfd6c69d7/New%20Citation%20List

                int n = url.indexOf("//");
                if (n > 0) {
                    n = url.indexOf("/", n + 2);
                    if (n > 0) {
                        String path = url.substring(n);
                        if (!path.startsWith("/access/content")) {
                            res.sendRedirect(url);
                            return;
                        }
                    }
                }

                ContentResource resource = null;
                try {
                    resource = contentHostingService.getResource(id);
                } catch (IdUnusedException e) {
                    throw new EntityNotDefinedException(e.getId());
                } catch (PermissionException e) {
                    throw new EntityPermissionException(e.getUser(), e.getLock(), e.getResource());
                } catch (TypeException e) {
                    throw new EntityNotDefinedException(id);
                }

                // we only do copyright on resources. I.e. not on inline things,which are MULTIMEDIA
                if (item.getType() == SimplePageItem.RESOURCE && needsCopyright(resource)) {
                    throw new EntityCopyrightException(resource.getReference());
                }
                try {
                    // Wrap it in any filtering needed.
                    resource = contentFilterService.wrap(resource);

                    // following cast is redundant is current kernels, but is needed for Sakai 2.6.1
                    long len = (long) resource.getContentLength();
                    String contentType = resource.getContentType();

                    //    for url resource type, encode a redirect to the body URL
                    // in 2.10 have to check resourcetype, but in previous releasese
                    // it doesn't get copied in site copy, so check content type. 10 doesn't set the contenttype to url
                    // so we have to check both to work in all versions
                    if (contentType.equalsIgnoreCase(ResourceProperties.TYPE_URL)
                            || "org.sakaiproject.content.types.urlResource"
                                    .equalsIgnoreCase(resource.getResourceType())) {
                        if (len < MAX_URL_LENGTH) {
                            byte[] content = resource.getContent();
                            if ((content == null) || (content.length == 0)) {
                                throw new IdUnusedException(ref.getReference());
                            }
                            //    An invalid URI format will get caught by the
                            //    outermost catch block
                            URI uri = new URI(new String(content, "UTF-8"));
                            eventTrackingService.post(
                                    eventTrackingService.newEvent(ContentHostingService.EVENT_RESOURCE_READ,
                                            resource.getReference(null), false));
                            res.sendRedirect(uri.toASCIIString());
                        } else {
                            //    we have a text/url mime type, but the body is too
                            //    long to issue as a redirect
                            throw new EntityNotDefinedException(ref.getReference());
                        }
                    } else {

                        //    use the last part, the file name part of the id, for
                        //    the download file name
                        String fileName = Web.encodeFileName(req, Validator.getFileName(ref.getId()));

                        String disposition = null;

                        boolean inline = false;
                        if (Validator.letBrowserInline(contentType)) {
                            // type can be inline, but if HTML we have more checks to do
                            if (inlineHtml || (!"text/html".equalsIgnoreCase(contentType)
                                    && !"application/xhtml+xml".equals(contentType)))
                                // easy cases: not HTML or HTML always OK
                                inline = true;
                            else {
                                // HTML and html is not allowed globally. code copied from BaseContentServices
                                ResourceProperties rp = resource.getProperties();

                                boolean fileInline = false;
                                boolean folderInline = false;

                                try {
                                    fileInline = rp.getBooleanProperty(ResourceProperties.PROP_ALLOW_INLINE);
                                } catch (EntityPropertyNotDefinedException e) {
                                    // we expect this so nothing to do!
                                }

                                if (!fileInline)
                                    try {
                                        folderInline = resource.getContainingCollection().getProperties()
                                                .getBooleanProperty(ResourceProperties.PROP_ALLOW_INLINE);
                                    } catch (EntityPropertyNotDefinedException e) {
                                        // we expect this so nothing to do!
                                    }

                                if (fileInline || folderInline) {
                                    inline = true;
                                }
                            }
                        }

                        if (inline) {
                            disposition = "inline; filename=\"" + fileName + "\"";
                        } else {
                            disposition = "attachment; filename=\"" + fileName + "\"";
                        }

                        // NOTE: Only set the encoding on the content we have
                        // to.
                        // Files uploaded by the user may have been created with
                        // different encodings, such as ISO-8859-1;
                        // rather than (sometimes wrongly) saying its UTF-8, let
                        // the browser auto-detect the encoding.
                        // If the content was created through the WYSIWYG
                        // editor, the encoding does need to be set (UTF-8).
                        String encoding = resource.getProperties()
                                .getProperty(ResourceProperties.PROP_CONTENT_ENCODING);
                        if (encoding != null && encoding.length() > 0) {
                            contentType = contentType + "; charset=" + encoding;
                        }

                        // from contenthosting

                        res.addHeader("Cache-Control", "must-revalidate, private");
                        res.addHeader("Expires", "-1");
                        ResourceProperties rp = resource.getProperties();
                        long lastModTime = 0;

                        try {
                            Time modTime = rp.getTimeProperty(ResourceProperties.PROP_MODIFIED_DATE);
                            lastModTime = modTime.getTime();
                        } catch (Exception e1) {
                            M_log.info("Could not retrieve modified time for: " + resource.getId());
                        }

                        // KNL-1316 tell the browser when our file was last modified for caching reasons
                        if (lastModTime > 0) {
                            SimpleDateFormat rfc1123Date = new SimpleDateFormat(RFC1123_DATE, LOCALE_US);
                            rfc1123Date.setTimeZone(TimeZone.getTimeZone("GMT"));
                            res.addHeader("Last-Modified", rfc1123Date.format(lastModTime));
                        }

                        // KNL-1316 let's see if the user already has a cached copy. Code copied and modified from Tomcat DefaultServlet.java
                        long headerValue = req.getDateHeader("If-Modified-Since");
                        if (headerValue != -1 && (lastModTime < headerValue + 1000)) {
                            // The entity has not been modified since the date specified by the client. This is not an error case.
                            res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                            return;
                        }

                        ArrayList<Range> ranges = parseRange(req, res, len);

                        if (req.getHeader("Range") == null || (ranges == null) || (ranges.isEmpty())) {

                            // stream the content using a small buffer to keep memory managed
                            InputStream content = null;
                            OutputStream out = null;

                            try {
                                content = resource.streamContent();
                                if (content == null) {
                                    throw new IdUnusedException(ref.getReference());
                                }

                                res.setContentType(contentType);
                                res.addHeader("Content-Disposition", disposition);
                                res.addHeader("Accept-Ranges", "bytes");

                                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4187336
                                if (len <= Integer.MAX_VALUE) {
                                    res.setContentLength((int) len);
                                } else {
                                    res.addHeader("Content-Length", Long.toString(len));
                                }

                                // set the buffer of the response to match what we are reading from the request
                                if (len < STREAM_BUFFER_SIZE) {
                                    res.setBufferSize((int) len);
                                } else {
                                    res.setBufferSize(STREAM_BUFFER_SIZE);
                                }

                                out = res.getOutputStream();

                                copyRange(content, out, 0, len - 1);
                            } catch (ServerOverloadException e) {
                                throw e;
                            } catch (Exception ignore) {
                            } finally {
                                // be a good little program and close the stream - freeing up valuable system resources
                                if (content != null) {
                                    content.close();
                                }

                                if (out != null) {
                                    try {
                                        out.close();
                                    } catch (Exception ignore) {
                                    }
                                }
                            }

                            // Track event - only for full reads
                            eventTrackingService.post(
                                    eventTrackingService.newEvent(ContentHostingService.EVENT_RESOURCE_READ,
                                            resource.getReference(null), false));

                        } else {
                            // Output partial content. Adapted from Apache Tomcat 5.5.27 DefaultServlet.java

                            res.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

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

                                // Single response

                                Range range = (Range) ranges.get(0);
                                res.addHeader("Content-Range",
                                        "bytes " + range.start + "-" + range.end + "/" + range.length);
                                long length = range.end - range.start + 1;
                                if (length < Integer.MAX_VALUE) {
                                    res.setContentLength((int) length);
                                } else {
                                    // Set the content-length as String to be able to use a long
                                    res.setHeader("content-length", "" + length);
                                }

                                res.addHeader("Content-Disposition", disposition);

                                if (contentType != null) {
                                    res.setContentType(contentType);
                                }

                                // stream the content using a small buffer to keep memory managed
                                InputStream content = null;
                                OutputStream out = null;

                                try {
                                    content = resource.streamContent();
                                    if (content == null) {
                                        throw new IdUnusedException(ref.getReference());
                                    }

                                    // set the buffer of the response to match what we are reading from the request
                                    if (len < STREAM_BUFFER_SIZE) {
                                        res.setBufferSize((int) len);
                                    } else {
                                        res.setBufferSize(STREAM_BUFFER_SIZE);
                                    }

                                    out = res.getOutputStream();

                                    copyRange(content, out, range.start, range.end);

                                } catch (ServerOverloadException e) {
                                    throw e;
                                } catch (SocketException e) {
                                    //a socket exception usualy means the client aborted the connection or similar
                                    if (M_log.isDebugEnabled()) {
                                        M_log.debug("SocketExcetion", e);
                                    }
                                } catch (Exception ignore) {
                                } finally {
                                    // be a good little program and close the stream - freeing up valuable system resources
                                    IOUtils.closeQuietly(content);
                                    IOUtils.closeQuietly(out);
                                }

                            } else {

                                // Multipart response

                                res.setContentType("multipart/byteranges; boundary=" + MIME_SEPARATOR);

                                // stream the content using a small buffer to keep memory managed
                                OutputStream out = null;

                                try {
                                    // set the buffer of the response to match what we are reading from the request
                                    if (len < STREAM_BUFFER_SIZE) {
                                        res.setBufferSize((int) len);
                                    } else {
                                        res.setBufferSize(STREAM_BUFFER_SIZE);
                                    }

                                    out = res.getOutputStream();

                                    copyRanges(resource, out, ranges.iterator(), contentType);

                                } catch (SocketException e) {
                                    //a socket exception usualy means the client aborted the connection or similar
                                    if (M_log.isDebugEnabled()) {
                                        M_log.debug("SocketExcetion", e);
                                    }
                                } catch (Exception ignore) {
                                    M_log.error("Swallowing exception", ignore);
                                } finally {
                                    // be a good little program and close the stream - freeing up valuable system resources
                                    IOUtils.closeQuietly(out);
                                }

                            } // output multiple ranges

                        } // output partial content 

                    }

                } catch (Exception t) {
                    throw new EntityNotDefinedException(ref.getReference());
                    // following won't work in 2.7.1
                    // throw new EntityNotDefinedException(ref.getReference(), t);
                }

                // not sure why we're trapping exceptions and calling them not defined, but
                // a few types are needed by the caller
            } catch (EntityCopyrightException ce) {
                // copyright exception needs to go as is, to give copyright alert
                throw ce;
            } catch (EntityPermissionException pe) {
                // also want permission exceptions; it will generate a login page
                throw pe;
            } catch (Exception ex) {
                throw new EntityNotDefinedException(ref.getReference());
            } finally {
                if (pushedAdvisor)
                    securityService.popAdvisor();
            }
        }
    };
}

From source file:org.apache.catalina.servlets.DefaultServlet.java

/**
 * Serve the specified resource, optionally including the data content.
 *
 * @param context  The servlet request we are processing
 * @param content  Should the content be included?
 * @param method  Description of the Parameter
 * @throws IOException      if an input/output error occurs
 * @throws ServletException if a servlet-specified error occurs
 *//*ww w .ja  v  a  2  s  .  c  o m*/
protected void serveResource(ActionContext context, boolean content, String method)
        throws IOException, ServletException {

    //TODO: remove this hardcoding
    debug = 2;
    // Identify the requested resource path
    String path = getRelativePath(context.getRequest());

    if (path.indexOf("/.") > -1) {
        //MAC OSX Fix
        return;
    }

    if (debug > 0) {
        if (content) {
            log("DefaultServlet.serveResource:  Serving resource '" + path + "' headers and data");
        } else {
            log("DefaultServlet.serveResource:  Serving resource '" + path + "' headers only");
        }
    }

    // Retrieve the Catalina context and Resources implementation

    Connection db = null;
    ModuleContext resources = null;
    ResourceInfo resourceInfo = null;
    SystemStatus thisSystem = null;
    boolean status = true;
    try {
        //System.out.println("DefaultServlet-> Serving Resource " + (content ? "WITH CONTENT" : "WITHOUT CONTENT"));
        db = this.getConnection(context);
        resources = getCFSResources(db, context);
        if (resources == null) {
            context.getResponse().sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }
        thisSystem = this.getSystemStatus(context);
        if (method.equals(METHOD_GET)) {
            Object current = resources.lookup(thisSystem, db, path);
        }
        resourceInfo = new ResourceInfo(thisSystem, path, resources);
    } catch (SQLException e) {
        e.printStackTrace(System.out);
        context.getResponse().sendError(CFS_SQLERROR, e.getMessage());
        status = false;
    } catch (Exception e) {
    } finally {
        this.freeConnection(db, context);
    }
    if (!status) {
        return;
    }

    if (!resourceInfo.exists) {
        context.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND, context.getRequest().getRequestURI());
        return;
    }

    // If the resource is not a collection, and the resource path
    // ends with "/" or "\", return NOT FOUND
    if (!resourceInfo.collection) {
        if (path.endsWith("/") || (path.endsWith("\\"))) {
            context.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND,
                    context.getRequest().getRequestURI());
            return;
        }
    }

    // Check if the conditions specified in the optional If headers are
    // satisfied.
    if (!resourceInfo.collection) {

        // Checking If headers
        boolean included = (context.getRequest().getAttribute(Globals.INCLUDE_CONTEXT_PATH_ATTR) != null);
        if (!included && !checkIfHeaders(context.getRequest(), context.getResponse(), resourceInfo)) {
            return;
        }
    }

    // Find content type
    String contentType = getServletContext().getMimeType(resourceInfo.clientFilename);

    Vector ranges = null;

    if (resourceInfo.collection) {

        // Skip directory listings if we have been configured to
        // suppress them
        if (!listings) {
            context.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND,
                    context.getRequest().getRequestURI());
            return;
        }
        contentType = "text/html;charset=UTF-8";

    } else {
        // Parse range specifier
        ranges = parseRange(context.getRequest(), context.getResponse(), resourceInfo);
        // ETag header
        context.getResponse().setHeader("ETag", getETag(resourceInfo));
        // Last-Modified header
        if (debug > 0) {
            log("DefaultServlet.serveFile:  lastModified='" + (new Timestamp(resourceInfo.date)).toString()
                    + "'");
        }
        context.getResponse().setHeader("Last-Modified", resourceInfo.httpDate);
    }

    ServletOutputStream ostream = null;
    PrintWriter writer = null;

    if (content) {
        // Trying to retrieve the servlet output stream
        try {
            ostream = context.getResponse().getOutputStream();
        } catch (IllegalStateException e) {
            // If it fails, we try to get a Writer instead if we're
            // trying to serve a text file
            if ((contentType == null) || (contentType.startsWith("text"))) {
                writer = context.getResponse().getWriter();
            } else {
                throw e;
            }
        }
    }

    if ((resourceInfo.collection) || (((ranges == null) || (ranges.isEmpty()))
            && (context.getRequest().getHeader("Range") == null))) {

        // Set the appropriate output headers
        if (contentType != null) {
            if (debug > 0) {
                log("DefaultServlet.serveFile:  contentType='" + contentType + "'");
            }
            context.getResponse().setContentType(contentType);
        }
        long contentLength = resourceInfo.length;
        if ((!resourceInfo.collection) && (contentLength >= 0)) {
            if (debug > 0) {
                log("DefaultServlet.serveFile:  contentLength=" + contentLength);
            }
            context.getResponse().setContentLength((int) contentLength);
        }
        if (resourceInfo.collection) {
            if (content) {
                // Serve the directory browser
                resourceInfo.setStream(render(context.getRequest().getContextPath(), resourceInfo));
            }
        }
        // Copy the input stream to our output stream (if requested)
        if (content) {
            try {
                context.getResponse().setBufferSize(output);
            } catch (IllegalStateException e) {
                // Silent catch
            }
            if (ostream != null) {
                copy(resourceInfo, ostream);
            } else {
                copy(resourceInfo, writer);
            }
        }
    } else {
        if ((ranges == null) || (ranges.isEmpty())) {
            return;
        }
        // Partial content response.
        context.getResponse().setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
        if (ranges.size() == 1) {
            Range range = (Range) ranges.elementAt(0);
            context.getResponse().addHeader("Content-Range",
                    "bytes " + range.start + "-" + range.end + "/" + range.length);
            context.getResponse().setContentLength((int) (range.end - range.start + 1));

            if (contentType != null) {
                if (debug > 0) {
                    log("DefaultServlet.serveFile:  contentType='" + contentType + "'");
                }
                context.getResponse().setContentType(contentType);
            }

            if (content) {
                try {
                    context.getResponse().setBufferSize(output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                if (ostream != null) {
                    copy(resourceInfo, ostream, range);
                } else {
                    copy(resourceInfo, writer, range);
                }
            }
        } else {

            context.getResponse().setContentType("multipart/byteranges; boundary=" + mimeSeparation);

            if (content) {
                try {
                    context.getResponse().setBufferSize(output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                if (ostream != null) {
                    copy(resourceInfo, ostream, ranges.elements(), contentType);
                } else {
                    copy(resourceInfo, writer, ranges.elements(), contentType);
                }
            }
        }
    }
}

From source file:org.structr.web.servlet.HtmlServlet.java

private void streamFile(SecurityContext securityContext, final File file, HttpServletRequest request,
        HttpServletResponse response, final EditMode edit) throws IOException {

    if (!securityContext.isVisible(file)) {

        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;//from w w  w. j  a  v  a  2s  .  co  m

    }

    final ServletOutputStream out = response.getOutputStream();
    final String downloadAsFilename = request.getParameter(DOWNLOAD_AS_FILENAME_KEY);
    final Map<String, Object> callbackMap = new LinkedHashMap<>();

    // make edit mode available in callback method
    callbackMap.put("editMode", edit);

    if (downloadAsFilename != null) {
        // Set Content-Disposition header to suggest a default filename and force a "save-as" dialog
        // See:
        // http://en.wikipedia.org/wiki/MIME#Content-Disposition,
        // http://tools.ietf.org/html/rfc2183
        // http://tools.ietf.org/html/rfc1806
        // http://tools.ietf.org/html/rfc2616#section-15.5 and http://tools.ietf.org/html/rfc2616#section-19.5.1
        response.addHeader("Content-Disposition", "attachment; filename=\"" + downloadAsFilename + "\"");

        callbackMap.put("requestedFileName", downloadAsFilename);
    }

    if (!EditMode.WIDGET.equals(edit) && notModifiedSince(request, response, file, false)) {

        out.flush();
        out.close();

        callbackMap.put("statusCode", HttpServletResponse.SC_NOT_MODIFIED);

    } else {

        final String downloadAsDataUrl = request.getParameter(DOWNLOAD_AS_DATA_URL_KEY);
        if (downloadAsDataUrl != null) {

            IOUtils.write(FileHelper.getBase64String(file), out);
            response.setContentType("text/plain");
            response.setStatus(HttpServletResponse.SC_OK);

            out.flush();
            out.close();

            callbackMap.put("statusCode", HttpServletResponse.SC_OK);

        } else {

            // 2b: stream file to response
            final InputStream in = file.getInputStream();
            final String contentType = file.getContentType();

            if (contentType != null) {

                response.setContentType(contentType);

            } else {

                // Default
                response.setContentType("application/octet-stream");
            }

            final String range = request.getHeader("Range");

            try {

                if (StringUtils.isNotEmpty(range)) {

                    final long len = file.getSize();
                    long start = 0;
                    long end = len - 1;

                    final Matcher matcher = Pattern.compile("bytes=(?<start>\\d*)-(?<end>\\d*)").matcher(range);

                    if (matcher.matches()) {
                        String startGroup = matcher.group("start");
                        start = startGroup.isEmpty() ? start : Long.valueOf(startGroup);
                        start = Math.max(0, start);

                        String endGroup = matcher.group("end");
                        end = endGroup.isEmpty() ? end : Long.valueOf(endGroup);
                        end = end > len - 1 ? len - 1 : end;
                    }

                    long contentLength = end - start + 1;

                    // Tell the client that we support byte ranges
                    response.setHeader("Accept-Ranges", "bytes");
                    response.setHeader("Content-Range", String.format("bytes %s-%s/%s", start, end, len));
                    response.setHeader("Content-Length", String.format("%s", contentLength));

                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                    callbackMap.put("statusCode", HttpServletResponse.SC_PARTIAL_CONTENT);

                    IOUtils.copyLarge(in, out, start, contentLength);

                } else {

                    response.setStatus(HttpServletResponse.SC_OK);
                    callbackMap.put("statusCode", HttpServletResponse.SC_OK);

                    IOUtils.copyLarge(in, out);

                }

            } catch (Throwable t) {

            } finally {

                if (out != null) {

                    try {
                        // 3: output content
                        out.flush();
                        out.close();

                    } catch (Throwable t) {
                    }
                }

                if (in != null) {
                    in.close();
                }

                response.setStatus(HttpServletResponse.SC_OK);
            }
        }
    }

    // WIDGET mode means "opened in frontend", which we don't want to count as an external download
    if (!EditMode.WIDGET.equals(edit)) {

        // call onDownload callback
        try {

            file.invokeMethod("onDownload", Collections.EMPTY_MAP, false);

        } catch (FrameworkException fex) {
            fex.printStackTrace();
        }
    }
}

From source file:org.gaul.s3proxy.S3ProxyHandler.java

private void handleGetBlob(HttpServletRequest request, HttpServletResponse response, BlobStore blobStore,
        String containerName, String blobName) throws IOException, S3Exception {
    int status = HttpServletResponse.SC_OK;
    GetOptions options = new GetOptions();

    String ifMatch = request.getHeader(HttpHeaders.IF_MATCH);
    if (ifMatch != null) {
        options.ifETagMatches(ifMatch);//from  w  w w  . j  a v a2 s.  c  o m
    }

    String ifNoneMatch = request.getHeader(HttpHeaders.IF_NONE_MATCH);
    if (ifNoneMatch != null) {
        options.ifETagDoesntMatch(ifNoneMatch);
    }

    long ifModifiedSince = request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
    if (ifModifiedSince != -1) {
        options.ifModifiedSince(new Date(ifModifiedSince));
    }

    long ifUnmodifiedSince = request.getDateHeader(HttpHeaders.IF_UNMODIFIED_SINCE);
    if (ifUnmodifiedSince != -1) {
        options.ifUnmodifiedSince(new Date(ifUnmodifiedSince));
    }

    String range = request.getHeader(HttpHeaders.RANGE);
    if (range != null && range.startsWith("bytes=") &&
    // ignore multiple ranges
            range.indexOf(',') == -1) {
        range = range.substring("bytes=".length());
        String[] ranges = range.split("-", 2);
        if (ranges[0].isEmpty()) {
            options.tail(Long.parseLong(ranges[1]));
        } else if (ranges[1].isEmpty()) {
            options.startAt(Long.parseLong(ranges[0]));
        } else {
            options.range(Long.parseLong(ranges[0]), Long.parseLong(ranges[1]));
        }
        status = HttpServletResponse.SC_PARTIAL_CONTENT;
    }

    Blob blob;
    try {
        blob = blobStore.getBlob(containerName, blobName, options);
    } catch (IllegalArgumentException iae) {
        // TODO: correct mapping?
        throw new S3Exception(S3ErrorCode.INVALID_RANGE, iae);
    }
    if (blob == null) {
        throw new S3Exception(S3ErrorCode.NO_SUCH_KEY);
    }

    response.setStatus(status);

    if (corsAllowAll) {
        response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
    }

    addMetadataToResponse(request, response, blob.getMetadata());
    // TODO: handles only a single range due to jclouds limitations
    Collection<String> contentRanges = blob.getAllHeaders().get(HttpHeaders.CONTENT_RANGE);
    if (!contentRanges.isEmpty()) {
        response.addHeader(HttpHeaders.CONTENT_RANGE, contentRanges.iterator().next());
        response.addHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
    }

    try (InputStream is = blob.getPayload().openStream(); OutputStream os = response.getOutputStream()) {
        ByteStreams.copy(is, os);
        os.flush();
    }
}

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

/**
 * Serve the specified resource, optionally including the data content.
 *
 * @param req The servlet request we are processing
 * @param resp The servlet response we are creating
 * @param content Should the content be included?
 * @exception IOException if an input/output error occurs
 * @exception ServletException if a servlet-specified error occurs
 * @throws RpcException//from  w w w  . j av a2s  .  c o  m
 * @throws InsufficientPermissionsException
 * @throws ObjectNotFoundException
 */
protected void serveResource(HttpServletRequest req, HttpServletResponse resp, boolean content)
        throws IOException, ServletException, ObjectNotFoundException, InsufficientPermissionsException,
        RpcException {

    // Identify the requested resource path
    String path = getRelativePath(req);
    if (logger.isDebugEnabled())
        if (content)
            logger.debug("Serving resource '" + path + "' headers and data");
        else
            logger.debug("Serving resource '" + path + "' headers only");

    User user = getUser(req);
    boolean exists = true;
    Object resource = null;
    FileHeader file = null;
    Folder folder = null;
    try {
        resource = getService().getResourceAtPath(user.getId(), path, true);
    } catch (ObjectNotFoundException e) {
        exists = false;
    } catch (RpcException e) {
        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
        return;
    }

    if (!exists) {
        resp.sendError(HttpServletResponse.SC_NOT_FOUND, req.getRequestURI());
        return;
    }

    if (resource instanceof Folder)
        folder = (Folder) resource;
    else
        file = (FileHeader) resource;

    // If the resource is not a collection, and the resource path
    // ends with "/" or "\", return NOT FOUND
    if (folder == null)
        if (path.endsWith("/") || path.endsWith("\\")) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND, req.getRequestURI());
            return;
        }

    // Check if the conditions specified in the optional If headers are
    // satisfied.
    if (folder == null)
        // Checking If headers
        if (!checkIfHeaders(req, resp, file, null))
            return;

    // Find content type.
    String contentType = null;
    if (file != null) {
        contentType = file.getCurrentBody().getMimeType();
        if (contentType == null) {
            contentType = getServletContext().getMimeType(file.getName());
            file.getCurrentBody().setMimeType(contentType);
        }
    } else
        contentType = "text/html;charset=UTF-8";

    ArrayList ranges = null;
    long contentLength = -1L;

    if (file != null) {
        // Accept ranges header
        resp.setHeader("Accept-Ranges", "bytes");
        // Parse range specifier
        ranges = parseRange(req, resp, file, null);
        // ETag header
        resp.setHeader("ETag", getETag(file, null));
        // Last-Modified header
        resp.setHeader("Last-Modified", getLastModifiedHttp(file.getAuditInfo()));
        // Get content length
        contentLength = file.getCurrentBody().getFileSize();
        // Special case for zero length files, which would cause a
        // (silent) ISE when setting the output buffer size
        if (contentLength == 0L)
            content = false;
    }

    ServletOutputStream ostream = null;
    PrintWriter writer = null;

    if (content)
        try {
            ostream = resp.getOutputStream();
        } catch (IllegalStateException e) {
            // If it fails, we try to get a Writer instead if we're
            // trying to serve a text file
            if (contentType == null || contentType.startsWith("text") || contentType.endsWith("xml"))
                writer = resp.getWriter();
            else
                throw e;
        }

    if (folder != null || (ranges == null || ranges.isEmpty()) && req.getHeader("Range") == null
            || ranges == FULL) {
        // Set the appropriate output headers
        if (contentType != null) {
            if (logger.isDebugEnabled())
                logger.debug("DefaultServlet.serveFile:  contentType='" + contentType + "'");
            resp.setContentType(contentType);
        }
        if (file != null && contentLength >= 0) {
            if (logger.isDebugEnabled())
                logger.debug("DefaultServlet.serveFile:  contentLength=" + contentLength);
            if (contentLength < Integer.MAX_VALUE)
                resp.setContentLength((int) contentLength);
            else
                // Set the content-length as String to be able to use a long
                resp.setHeader("content-length", "" + contentLength);
        }

        InputStream renderResult = null;
        if (folder != null)
            if (content)
                // Serve the directory browser
                renderResult = renderHtml(req.getContextPath(), path, folder, req);

        // Copy the input stream to our output stream (if requested)
        if (content) {
            try {
                resp.setBufferSize(output);
            } catch (IllegalStateException e) {
                // Silent catch
            }
            if (ostream != null)
                copy(file, renderResult, ostream, req, null);
            else
                copy(file, renderResult, writer, req, null);
            updateAccounting(user, new Date(), contentLength);
        }
    } else {
        if (ranges == null || ranges.isEmpty())
            return;
        // Partial content response.
        resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

        if (ranges.size() == 1) {
            Range range = (Range) ranges.get(0);
            resp.addHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + range.length);
            long length = range.end - range.start + 1;
            if (length < Integer.MAX_VALUE)
                resp.setContentLength((int) length);
            else
                // Set the content-length as String to be able to use a long
                resp.setHeader("content-length", "" + length);

            if (contentType != null) {
                if (logger.isDebugEnabled())
                    logger.debug("DefaultServlet.serveFile:  contentType='" + contentType + "'");
                resp.setContentType(contentType);
            }

            if (content) {
                try {
                    resp.setBufferSize(output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                if (ostream != null)
                    copy(file, ostream, range, req, null);
                else
                    copy(file, writer, range, req, null);
                updateAccounting(user, new Date(), contentLength);
            }

        } else {

            resp.setContentType("multipart/byteranges; boundary=" + mimeSeparation);

            if (content) {
                try {
                    resp.setBufferSize(output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                if (ostream != null)
                    copy(file, ostream, ranges.iterator(), contentType, req, null);
                else
                    copy(file, writer, ranges.iterator(), contentType, req, null);
            }

        }

    }

}

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

/**
 * Serve the specified resource, optionally including the data content.<p>
 *
 * @param request the servlet request we are processing
 * @param response the servlet response we are creating
 * @param content should the content be included?
 *
 * @throws IOException if an input/output error occurs
 *///  w  w  w . jav a  2 s  .com
protected void serveResource(HttpServletRequest request, HttpServletResponse response, boolean content)
        throws IOException {

    // Identify the requested resource path
    String path = getRelativePath(request);
    if (LOG.isDebugEnabled()) {
        if (content) {
            LOG.debug(Messages.get().getBundle().key(Messages.LOG_SERVE_ITEM_1, path));
        } else {
            LOG.debug(Messages.get().getBundle().key(Messages.LOG_SERVE_ITEM_HEADER_1, path));
        }
    }

    I_CmsRepositoryItem item = null;
    try {
        item = m_session.getItem(path);
    } catch (CmsException ex) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);

        if (LOG.isDebugEnabled()) {
            LOG.debug(Messages.get().getBundle().key(Messages.LOG_ITEM_NOT_FOUND_1, path));
        }

        return;
    }

    // If the resource is not a collection, and the resource path
    // ends with "/" or "\", return NOT FOUND
    if (!item.isCollection()) {
        if (path.endsWith("/") || (path.endsWith("\\"))) {

            response.setStatus(HttpServletResponse.SC_NOT_FOUND);

            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_ITEM_NOT_FOUND_1, path));
            }

            return;
        }
    }

    // Find content type.
    String contentType = item.getMimeType();
    if (contentType == null) {
        contentType = getServletContext().getMimeType(item.getName());
    }

    ArrayList<CmsWebdavRange> ranges = null;
    long contentLength = -1L;

    if (item.isCollection()) {

        // Skip directory listings if we have been configured to suppress them
        if (!m_listings) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        contentType = "text/html;charset=UTF-8";

    } else {

        // Parse range specifier
        ranges = parseRange(request, response, item);

        // ETag header
        response.setHeader(HEADER_ETAG, getETag(item));

        // Last-Modified header
        response.setHeader(HEADER_LASTMODIFIED, HTTP_DATE_FORMAT.format(new Date(item.getLastModifiedDate())));

        // Get content length
        contentLength = item.getContentLength();

        // Special case for zero length files, which would cause a
        // (silent) ISE when setting the output buffer size
        if (contentLength == 0L) {
            content = false;
        }

    }

    ServletOutputStream ostream = null;
    PrintWriter writer = null;

    if (content) {

        // Trying to retrieve the servlet output stream
        try {
            ostream = response.getOutputStream();
        } catch (IllegalStateException e) {

            // If it fails, we try to get a Writer instead if we're
            // trying to serve a text file
            if ((contentType == null) || (contentType.startsWith("text")) || (contentType.endsWith("xml"))) {
                writer = response.getWriter();
            } else {
                throw e;
            }
        }

    }

    if ((item.isCollection())
            || (((ranges == null) || (ranges.isEmpty())) && (request.getHeader(HEADER_RANGE) == null))
            || (ranges == FULL_RANGE)) {

        // Set the appropriate output headers
        if (contentType != null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_SERVE_ITEM_CONTENT_TYPE_1, contentType));
            }
            response.setContentType(contentType);
        }

        if ((!item.isCollection()) && (contentLength >= 0)) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_SERVE_ITEM_CONTENT_LENGTH_1,
                        new Long(contentLength)));
            }

            if (contentLength < Integer.MAX_VALUE) {
                response.setContentLength((int) contentLength);
            } else {

                // Set the content-length as String to be able to use a long
                response.setHeader(HEADER_CONTENTLENGTH, "" + contentLength);
            }
        }

        InputStream renderResult = null;
        if (item.isCollection()) {

            if (content) {
                // Serve the directory browser
                renderResult = renderHtml(request.getContextPath() + request.getServletPath(), item.getName());
            }

        }

        // Copy the input stream to our output stream (if requested)
        if (content) {
            try {
                response.setBufferSize(m_output);
            } catch (IllegalStateException e) {
                // Silent catch
            }
            if (ostream != null) {
                copy(item, renderResult, ostream);
            } else {
                copy(item, renderResult, writer);
            }
        }

    } else {

        if ((ranges == null) || (ranges.isEmpty())) {
            return;
        }

        // Partial content response.
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

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

            CmsWebdavRange range = ranges.get(0);
            response.addHeader(HEADER_CONTENTRANGE,
                    "bytes " + range.getStart() + "-" + range.getEnd() + "/" + range.getLength());
            long length = (range.getEnd() - range.getStart()) + 1;
            if (length < Integer.MAX_VALUE) {
                response.setContentLength((int) length);
            } else {
                // Set the content-length as String to be able to use a long
                response.setHeader(HEADER_CONTENTLENGTH, "" + length);
            }

            if (contentType != null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(Messages.get().getBundle().key(Messages.LOG_SERVE_ITEM_CONTENT_TYPE_1,
                            contentType));
                }
                response.setContentType(contentType);
            }

            if (content) {
                try {
                    response.setBufferSize(m_output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                if (ostream != null) {
                    copy(item, ostream, range);
                } else {
                    copy(item, writer, range);
                }
            }

        } else {

            response.setContentType("multipart/byteranges; boundary=" + MIME_SEPARATION);

            if (content) {
                try {
                    response.setBufferSize(m_output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                if (ostream != null) {
                    copy(item, ostream, ranges.iterator(), contentType);
                } else {
                    copy(item, writer, ranges.iterator(), contentType);
                }
            }

        }

    }
}

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 .ja  v  a  2 s.c  om
 * @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);
        }
    }

}