Example usage for javax.servlet.http HttpServletResponse setBufferSize

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

Introduction

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

Prototype

public void setBufferSize(int size);

Source Link

Document

Sets the preferred buffer size for the body of the response.

Usage

From source file:com.liferay.lms.servlet.SCORMFileServerServlet.java

/**
 * Procesa los metodos HTTP GET y POST.<br>
 * Busca en la ruta que se le ha pedido el comienzo del directorio
 * "contenidos" y sirve el fichero./*  www  . java2 s .c  o  m*/
 */
protected void processRequest(HttpServletRequest request, HttpServletResponse response, boolean content)
        throws ServletException, java.io.IOException {
    String mime_type;
    String charset;
    String patharchivo;
    String uri;

    try {
        User user = PortalUtil.getUser(request);

        if (user == null) {
            String userId = null;
            String companyId = null;
            Cookie[] cookies = ((HttpServletRequest) request).getCookies();
            if (Validator.isNotNull(cookies)) {
                for (Cookie c : cookies) {
                    if ("COMPANY_ID".equals(c.getName())) {
                        companyId = c.getValue();
                    } else if ("ID".equals(c.getName())) {
                        userId = hexStringToStringByAscii(c.getValue());
                    }
                }
            }

            if (userId != null && companyId != null) {
                try {
                    Company company = CompanyLocalServiceUtil.getCompany(Long.parseLong(companyId));
                    Key key = company.getKeyObj();

                    String userIdPlain = Encryptor.decrypt(key, userId);

                    user = UserLocalServiceUtil.getUser(Long.valueOf(userIdPlain));

                    // Now you can set the liferayUser into a thread local
                    // for later use or
                    // something like that.

                } catch (Exception pException) {
                    throw new RuntimeException(pException);
                }
            }
        }

        String rutaDatos = SCORMContentLocalServiceUtil.getBaseDir();

        // Se comprueba que el usuario tiene permisos para acceder.
        // Damos acceso a todo el mundo al directorio "personalizacion",
        // para permitir mostrar a todos la pantalla de identificacion.
        uri = URLDecoder.decode(request.getRequestURI(), "UTF-8");
        uri = uri.substring(uri.indexOf("scorm/") + "scorm/".length());
        patharchivo = rutaDatos + "/" + uri;

        String[] params = uri.split("/");
        long groupId = GetterUtil.getLong(params[1]);
        String uuid = params[2];
        SCORMContent scormContent = SCORMContentLocalServiceUtil.getSCORMContentByUuidAndGroupId(uuid, groupId);

        boolean allowed = false;
        if (user == null) {
            user = UserLocalServiceUtil.getDefaultUser(PortalUtil.getDefaultCompanyId());
        }
        PermissionChecker pc = PermissionCheckerFactoryUtil.create(user);
        allowed = pc.hasPermission(groupId, SCORMContent.class.getName(), scormContent.getScormId(),
                ActionKeys.VIEW);
        if (!allowed) {
            AssetEntry scormAsset = AssetEntryLocalServiceUtil.getEntry(SCORMContent.class.getName(),
                    scormContent.getPrimaryKey());
            long scormAssetId = scormAsset.getEntryId();
            int typeId = new Long((new SCORMLearningActivityType()).getTypeId()).intValue();
            long[] groupIds = user.getGroupIds();
            for (long gId : groupIds) {
                List<LearningActivity> acts = LearningActivityLocalServiceUtil
                        .getLearningActivitiesOfGroupAndType(gId, typeId);
                for (LearningActivity act : acts) {
                    String entryId = LearningActivityLocalServiceUtil.getExtraContentValue(act.getActId(),
                            "assetEntry");
                    if (Validator.isNotNull(entryId) && Long.valueOf(entryId) == scormAssetId) {
                        allowed = pc.hasPermission(gId, LearningActivity.class.getName(), act.getActId(),
                                ActionKeys.VIEW);
                        if (allowed) {
                            break;
                        }
                    }
                }
                if (allowed) {
                    break;
                }
            }

        }
        if (allowed) {

            File archivo = new File(patharchivo);

            // Si el archivo existe y no es un directorio se sirve. Si no,
            // no se hace nada.
            if (archivo.exists() && archivo.isFile()) {

                // El content type siempre antes del printwriter
                mime_type = MimeTypesUtil.getContentType(archivo);
                charset = "";
                if (archivo.getName().toLowerCase().endsWith(".html")
                        || archivo.getName().toLowerCase().endsWith(".htm")) {
                    mime_type = "text/html";
                    if (isISO(FileUtils.readFileToString(archivo))) {
                        charset = "ISO-8859-1";
                    }
                }
                if (archivo.getName().toLowerCase().endsWith(".swf")) {
                    mime_type = "application/x-shockwave-flash";
                }
                if (archivo.getName().toLowerCase().endsWith(".mp4")) {
                    mime_type = "video/mp4";
                }
                if (archivo.getName().toLowerCase().endsWith(".flv")) {
                    mime_type = "video/x-flv";
                }
                response.setContentType(mime_type);
                if (Validator.isNotNull(charset)) {
                    response.setCharacterEncoding(charset);

                }
                response.addHeader("Content-Type",
                        mime_type + (Validator.isNotNull(charset) ? "; " + charset : ""));
                /*if (archivo.getName().toLowerCase().endsWith(".swf")
                      || archivo.getName().toLowerCase().endsWith(".flv")) {
                   response.addHeader("Content-Length",
                String.valueOf(archivo.length()));
                }
                */
                if (archivo.getName().toLowerCase().endsWith("imsmanifest.xml")) {
                    FileInputStream fis = new FileInputStream(patharchivo);

                    String sco = ParamUtil.get(request, "scoshow", "");
                    Document manifest = SAXReaderUtil.read(fis);
                    if (sco.length() > 0) {

                        Element organizatEl = manifest.getRootElement().element("organizations")
                                .element("organization");
                        Element selectedItem = selectItem(organizatEl, sco);
                        if (selectedItem != null) {
                            selectedItem.detach();
                            java.util.List<Element> items = organizatEl.elements("item");
                            for (Element item : items) {

                                organizatEl.remove(item);
                            }
                            organizatEl.add(selectedItem);
                        }
                    }
                    //clean unused resources.
                    Element resources = manifest.getRootElement().element("resources");
                    java.util.List<Element> theResources = resources.elements("resource");
                    Element organizatEl = manifest.getRootElement().element("organizations")
                            .element("organization");
                    java.util.List<String> identifiers = getIdentifierRefs(organizatEl);
                    for (Element resource : theResources) {
                        String identifier = resource.attributeValue("identifier");
                        if (!identifiers.contains(identifier)) {
                            resources.remove(resource);
                        }
                    }
                    response.getWriter().print(manifest.asXML());
                    fis.close();
                    return;

                }

                if (mime_type.startsWith("text") || mime_type.endsWith("javascript")
                        || mime_type.equals("application/xml")) {

                    java.io.OutputStream out = response.getOutputStream();
                    FileInputStream fis = new FileInputStream(patharchivo);

                    byte[] buffer = new byte[512];
                    int i = 0;

                    while (fis.available() > 0) {
                        i = fis.read(buffer);
                        if (i == 512)
                            out.write(buffer);
                        else
                            out.write(buffer, 0, i);

                    }

                    fis.close();
                    out.flush();
                    out.close();
                    return;
                }
                //If not manifest
                String fileName = archivo.getName();
                long length = archivo.length();
                long lastModified = archivo.lastModified();
                String eTag = fileName + "_" + length + "_" + lastModified;
                long expires = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME;
                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;
                }
                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;
                }

                // 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));
                        }
                    }
                }
                boolean acceptsGzip = false;
                String disposition = "inline";

                if (mime_type.startsWith("text")) {
                    //String acceptEncoding = request.getHeader("Accept-Encoding");
                    // acceptsGzip = acceptEncoding != null && accepts(acceptEncoding, "gzip");
                    // mime_type += ";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 (!mime_type.startsWith("image")) {
                    String accept = request.getHeader("Accept");
                    disposition = accept != null && accepts(accept, mime_type) ? "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(archivo, "r");
                    output = response.getOutputStream();

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

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

                        if (content) {

                            // 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(mime_type);
                        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: " + mime_type);
                                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);
                }
            } else {
                //java.io.OutputStream out = response.getOutputStream();
                response.sendError(404);
                //out.write(uri.getBytes());
            }
        } else {
            response.sendError(401);
        }
    } catch (Exception e) {
        System.out.println("Error en el processRequest() de ServidorArchivos: " + e.getMessage());
    }
}

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

/**
  * Serve the specified resource, optionally including the data content.
  *//from   w w  w.jav a 2s .c o  m
  * @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
  * @throws InsufficientPermissionsException
  * @throws ObjectNotFoundException
  */
@Override
protected void serveResource(HttpServletRequest req, HttpServletResponse resp, boolean content)
        throws IOException, ServletException {
    boolean authDeferred = getAuthDeferred(req);
    String path = getInnerPath(req, PATH_FILES);
    if (path.equals(""))
        path = "/";
    try {
        path = URLDecoder.decode(path, "UTF-8");
    } catch (IllegalArgumentException e) {
        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
        return;
    }
    String progress = req.getParameter(PROGRESS_PARAMETER);

    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);
    User owner = getOwner(req);
    boolean exists = true;
    Object resource = null;
    FileHeader file = null;
    Folder folder = null;
    try {
        resource = getService().getResourceAtPath(owner.getId(), path, false);
    } catch (ObjectNotFoundException e) {
        exists = false;
    } catch (RpcException e) {
        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
        return;
    }

    if (!exists && authDeferred) {
        // We do not want to leak information if the request
        // was not authenticated.
        resp.sendError(HttpServletResponse.SC_FORBIDDEN);
        return;
    }

    if (resource instanceof Folder)
        folder = (Folder) resource;
    else
        file = (FileHeader) resource; // Note that file will be null, if (!exists).

    // Now it's time to perform the deferred authentication check.
    // Since regular signature checking was already performed,
    // we need to check the read-all flag or the signature-in-parameters.
    if (authDeferred) {
        if (file != null && !file.isReadForAll() && content) {
            // Check for GET with the signature in the request parameters.
            String auth = req.getParameter(AUTHORIZATION_PARAMETER);
            String dateParam = req.getParameter(DATE_PARAMETER);
            if (auth == null || dateParam == null) {
                // Check for a valid authentication cookie.
                if (req.getCookies() != null) {
                    boolean found = false;
                    for (Cookie cookie : req.getCookies())
                        if (Login.AUTH_COOKIE.equals(cookie.getName())) {
                            String cookieauth = cookie.getValue();
                            int sepIndex = cookieauth.indexOf(Login.COOKIE_SEPARATOR);
                            if (sepIndex == -1) {
                                handleAuthFailure(req, resp);
                                return;
                            }
                            String username = URLDecoder.decode(cookieauth.substring(0, sepIndex), "US-ASCII");
                            user = null;
                            try {
                                user = getService().findUser(username);
                            } catch (RpcException e) {
                                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
                                return;
                            }
                            if (user == null) {
                                resp.sendError(HttpServletResponse.SC_FORBIDDEN);
                                return;
                            }
                            req.setAttribute(USER_ATTRIBUTE, user);
                            String token = cookieauth.substring(sepIndex + 1);
                            if (user.getAuthToken() == null) {
                                resp.sendError(HttpServletResponse.SC_FORBIDDEN);
                                return;
                            }
                            if (!Arrays.equals(user.getAuthToken(), Base64.decodeBase64(token))) {
                                resp.sendError(HttpServletResponse.SC_FORBIDDEN);
                                return;
                            }
                            found = true;
                            break;
                        }
                    if (!found) {
                        handleAuthFailure(req, resp);
                        return;
                    }
                } else {
                    handleAuthFailure(req, resp);
                    return;
                }
            } else {
                long timestamp;
                try {
                    timestamp = DateUtil.parseDate(dateParam).getTime();
                } catch (DateParseException e) {
                    resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
                    return;
                }

                // Fetch the Authorization parameter and find the user specified in it.
                String[] authParts = auth.split(" ");
                if (authParts.length != 2) {
                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
                String username = authParts[0];
                String signature = authParts[1];
                user = null;
                try {
                    user = getService().findUser(username);
                } catch (RpcException e) {
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
                    return;
                }
                if (user == null) {
                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
                req.setAttribute(USER_ATTRIBUTE, user);

                // Remove the servlet path from the request URI.
                String p = req.getRequestURI();
                String servletPath = req.getContextPath() + req.getServletPath();
                p = p.substring(servletPath.length());
                // Validate the signature in the Authorization parameter.
                String data = req.getMethod() + dateParam + p;
                if (!isSignatureValid(signature, user, data)) {
                    resp.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }
            }
        } else if (folder != null && folder.isReadForAll() || file != null && file.isReadForAll()) {
            //This case refers to a folder or file with public privileges
            //For a read-for-all folder request, pretend the owner is making it.
            user = owner;
            req.setAttribute(USER_ATTRIBUTE, user);
        } else if (folder != null && !folder.isReadForAll()) {
            resp.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        } else {
            resp.sendError(HttpServletResponse.SC_FORBIDDEN);
            return;
        }
    }
    // 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;
        }

    // Workaround for IE's broken caching behavior.
    if (folder != null)
        resp.setHeader("Expires", "-1");

    // A request for upload progress.
    if (progress != null && content) {
        serveProgress(req, resp, progress, user, file);
        return;
    }

    // Fetch the version to retrieve, if specified.
    String verStr = req.getParameter(VERSION_PARAM);
    int version = 0;
    FileBody oldBody = null;
    if (verStr != null && file != null)
        try {
            version = Integer.valueOf(verStr);
        } catch (NumberFormatException e) {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, req.getRequestURI());
            return;
        }
    if (version > 0)
        try {
            oldBody = getService().getFileVersion(user.getId(), file.getId(), version);
        } catch (RpcException e) {
            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
            return;
        } catch (ObjectNotFoundException e) {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        } catch (InsufficientPermissionsException e) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
            return;
        }

    // Check if the conditions specified in the optional If headers are
    // satisfied. Doing this for folders would require recursive checking
    // for all of their children, which in turn would defy the purpose of
    // the optimization.
    if (folder == null) {
        // Checking If headers.
        if (!checkIfHeaders(req, resp, file, oldBody))
            return;
    } else if (!checkIfModifiedSince(req, resp, folder))
        return;

    // Find content type.
    String contentType = null;
    boolean isContentHtml = false;
    boolean expectJSON = false;

    if (file != null) {
        contentType = version > 0 ? oldBody.getMimeType() : file.getCurrentBody().getMimeType();
        if (contentType == null) {
            contentType = context.getMimeType(file.getName());
            file.getCurrentBody().setMimeType(contentType);
        }
    } else { // folder != null
        String accept = req.getHeader("Accept");
        // The order in this conditional pessimizes the common API case,
        // but is important for backwards compatibility with existing
        // clients who send no accept header and expect a JSON response.
        if (accept != null && accept.contains("text/html")) {
            contentType = "text/html;charset=UTF-8";
            isContentHtml = true;
            //this is the case when clients send the appropriate headers, the contentType is "text/html"
            //and expect a JSON response. The above check applies to FireGSS client
            expectJSON = !authDeferred ? true : false;
        } else if (authDeferred && req.getMethod().equals(METHOD_GET)) {
            contentType = "text/html;charset=UTF-8";
            isContentHtml = true;
            expectJSON = false;
        } else {
            contentType = "application/json;charset=UTF-8";
            expectJSON = true;
        }
    }

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

    if (file != null) {
        // Parse range specifier.
        ranges = parseRange(req, resp, file, oldBody);
        // ETag header
        resp.setHeader("ETag", getETag(file, oldBody));
        // Last-Modified header.
        String lastModified = oldBody == null ? getLastModifiedHttp(file.getAuditInfo())
                : getLastModifiedHttp(oldBody.getAuditInfo());
        resp.setHeader("Last-Modified", lastModified);
        // X-GSS-Metadata header.
        try {
            resp.setHeader("X-GSS-Metadata", renderJson(user, file, oldBody));
        } catch (InsufficientPermissionsException e) {
            resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
            return;
        }
        // Get content length.
        contentLength = version > 0 ? oldBody.getFileSize() : 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;
    } else
        // Set the folder X-GSS-Metadata header.
        try {
            resp.setHeader("X-GSS-Metadata", renderJsonMetadata(user, folder));
        } catch (InsufficientPermissionsException e) {
            resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
            return;
        }

    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("contentType='" + contentType + "'");
            resp.setContentType(contentType);
        }
        if (file != null && contentLength >= 0) {
            if (logger.isDebugEnabled())
                logger.debug("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;
        String relativePath = getRelativePath(req);
        String contextPath = req.getContextPath();
        String servletPath = req.getServletPath();
        String contextServletPath = contextPath + servletPath;
        if (folder != null && content)
            // Serve the directory browser for a public folder
            if (isContentHtml && !expectJSON) {
                try {
                    folder = getService().expandFolder(folder);
                } catch (ObjectNotFoundException e) {
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
                    return;
                } catch (RpcException e) {
                    //We send 500 instead of 404 because this folder has been loaded before in this method and it is
                    //impossible to not be found now
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, path);
                    return;
                }
                renderResult = renderHtml(contextServletPath, relativePath, folder, user);
            }
            // Serve the directory for an ordinary folder or for fireGSS client
            else
                try {
                    renderResult = renderJson(user, folder);
                } catch (InsufficientPermissionsException e) {
                    resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                    return;
                }

        // Copy the input stream to our output stream (if requested)
        if (content) {
            try {
                resp.setBufferSize(output);
            } catch (IllegalStateException e) {
                // Silent catch
            }
            try {
                if (file != null)
                    if (needsContentDisposition(req))
                        resp.setHeader("Content-Disposition",
                                "attachment; filename*=UTF-8''" + getDispositionFilename(file));
                    else
                        resp.setHeader("Content-Disposition",
                                "inline; filename*=UTF-8''" + getDispositionFilename(file));
                if (ostream != null)
                    copy(file, renderResult, ostream, req, oldBody);
                else
                    copy(file, renderResult, writer, req, oldBody);
                if (file != null)
                    updateAccounting(owner, new Date(), contentLength);
            } catch (ObjectNotFoundException e) {
                resp.sendError(HttpServletResponse.SC_NOT_FOUND);
                return;
            } catch (InsufficientPermissionsException e) {
                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                return;
            } catch (RpcException e) {
                resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }
        }
    } 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("contentType='" + contentType + "'");
                resp.setContentType(contentType);
            }

            if (content) {
                try {
                    resp.setBufferSize(output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                try {
                    if (ostream != null)
                        copy(file, ostream, range, req, oldBody);
                    else
                        copy(file, writer, range, req, oldBody);
                    updateAccounting(owner, new Date(), contentLength);
                } catch (ObjectNotFoundException e) {
                    resp.sendError(HttpServletResponse.SC_NOT_FOUND);
                    return;
                } catch (InsufficientPermissionsException e) {
                    resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                    return;
                } catch (RpcException e) {
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                    return;
                }
            }
        } else {
            resp.setContentType("multipart/byteranges; boundary=" + mimeSeparation);
            if (content) {
                try {
                    resp.setBufferSize(output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                try {
                    if (ostream != null)
                        copy(file, ostream, ranges.iterator(), contentType, req, oldBody);
                    else
                        copy(file, writer, ranges.iterator(), contentType, req, oldBody);
                    updateAccounting(owner, new Date(), contentLength);
                } catch (ObjectNotFoundException e) {
                    resp.sendError(HttpServletResponse.SC_NOT_FOUND);
                    return;
                } catch (InsufficientPermissionsException e) {
                    resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                    return;
                } catch (RpcException e) {
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                    return;
                }
            }
        }
    }
}

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

/**
 * Process the access request for a resource.
 * /*  w w w.j  a v  a  2 s.  co  m*/
 * @param req
 * @param req
 * @param res
 * @param ref
 * @param copyrightAcceptedRefs
 * @throws PermissionException
 * @throws IdUnusedException
 * @throws ServerOverloadException
 * @throws CopyrightException
 */
protected void handleAccessResource(HttpServletRequest req, HttpServletResponse res, Reference ref,
        Collection<String> copyrightAcceptedRefs) throws EntityPermissionException, EntityNotDefinedException,
        EntityAccessOverloadException, EntityCopyrightException {
    // we only access resources, not collections
    if (ref.getId().endsWith(Entity.SEPARATOR))
        throw new EntityNotDefinedException(ref.getReference());

    // need read permission
    if (!allowGetResource(ref.getId()))
        throw new EntityPermissionException(sessionManager.getCurrentSessionUserId(), AUTH_RESOURCE_READ,
                ref.getReference());

    ContentResource resource = null;
    try {
        resource = getResource(ref.getId());
    } 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(ref.getReference());
    }

    // if this entity requires a copyright agreement, and has not yet been set, get one
    if (((BaseResourceEdit) resource).requiresCopyrightAgreement()
            && !copyrightAcceptedRefs.contains(resource.getReference())) {
        throw new EntityCopyrightException(ref.getReference());
    }

    // Wrap up the resource if we need to.
    resource = m_contentFilterService.wrap(resource);

    // Set some headers to tell browsers to revalidate and check for updated files
    res.addHeader("Cache-Control", "must-revalidate, private");
    res.addHeader("Expires", "-1");

    try {
        long len = resource.getContentLength();
        String contentType = resource.getContentType();
        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));
        }

        // for url content type, encode a redirect to the body URL
        if (contentType.equalsIgnoreCase(ResourceProperties.TYPE_URL)) {
            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(EVENT_RESOURCE_READ, resource.getReference(null), false));

                //SAK-23587 process any macros present in this URL
                String decodedUrl = URLDecoder.decode(uri.toString(), "UTF-8");
                decodedUrl = expandMacros(decodedUrl);

                res.sendRedirect(decodedUrl);

            } 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 = Validator.getFileName(ref.getId());
            String disposition = null;

            if (Validator.letBrowserInline(contentType)) {
                // if this is an html file we have more checks
                String lcct = contentType.toLowerCase();
                if ((lcct.startsWith("text/") || lcct.startsWith("image/") || lcct.contains("html")
                        || lcct.contains("script"))
                        && m_serverConfigurationService.getBoolean(SECURE_INLINE_HTML, true)) {
                    // increased checks to handle more mime-types - https://jira.sakaiproject.org/browse/KNL-749

                    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) {
                        disposition = Web.buildContentDisposition(fileName, false);
                    }
                } else {
                    disposition = Web.buildContentDisposition(fileName, false);
                }
            }

            // drop through to attachment
            if (disposition == null) {
                disposition = Web.buildContentDisposition(fileName, true);
            }

            // 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;
            }

            // 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);
            res.addHeader("Accept-Ranges", "bytes");

            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);
                    // 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(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
                        if (content != null) {
                            content.close();
                        }

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

                } 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
                        if (out != null) {
                            try {
                                out.close();
                            } catch (IOException ignore) {
                                // ignore
                            }
                        }
                    }

                } // output multiple ranges

            } // output partial content 

        } // output resource

    } catch (Exception t) {
        throw new EntityNotDefinedException(ref.getReference(), t);
    }
}

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  ww  .  j av  a  2s.  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();
            }
        }
    };
}