org.sakaiproject.nakamura.files.pool.StreamHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.nakamura.files.pool.StreamHelper.java

Source

/**
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.sakaiproject.nakamura.files.pool;

import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
import static org.apache.sling.api.servlets.HttpConstants.HEADER_IF_MODIFIED_SINCE;
import static org.apache.sling.api.servlets.HttpConstants.HEADER_LAST_MODIFIED;

import org.apache.commons.io.IOUtils;
import org.apache.sling.api.resource.Resource;
import org.sakaiproject.nakamura.api.lite.StorageClientException;
import org.sakaiproject.nakamura.api.lite.StorageClientUtils;
import org.sakaiproject.nakamura.api.lite.accesscontrol.AccessDeniedException;
import org.sakaiproject.nakamura.api.lite.content.Content;
import org.sakaiproject.nakamura.api.lite.content.ContentManager;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import javax.jcr.RepositoryException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class StreamHelper {

    public void stream(HttpServletRequest request, ContentManager contentManager, Content node,
            String alternativeStream, HttpServletResponse response, Resource resource,
            ServletContext servletContext) throws IOException, StorageClientException, AccessDeniedException {
        InputStream dataStream = contentManager.getInputStream(node.getPath(), alternativeStream);

        if (dataStream == null) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        Map<String, Object> properties = node.getProperties();
        long modifTime = StorageClientUtils.toLong(
                properties.get(StorageClientUtils.getAltField(Content.LASTMODIFIED_FIELD, alternativeStream)));
        if (unmodified(request, modifTime)) {
            response.setStatus(SC_NOT_MODIFIED);
            return;
        }

        setHeaders(properties, resource, response, alternativeStream, servletContext);
        setContentLength(properties, response, alternativeStream);
        IOUtils.copyLarge(dataStream, response.getOutputStream());
        dataStream.close();
    }

    /**
     * Returns <code>true</code> if the request has a <code>If-Modified-Since</code> header
     * whose date value is later than the last modification time given as
     * <code>modifTime</code>.
     *
     * @param request
     *          The <code>ComponentRequest</code> checked for the
     *          <code>If-Modified-Since</code> header.
     * @param modifTime
     *          The last modification time to compare the header to.
     * @return <code>true</code> if the <code>modifTime</code> is less than or equal to the
     *         time of the <code>If-Modified-Since</code> header.
     */
    private boolean unmodified(HttpServletRequest request, long modifTime) {
        if (modifTime > 0) {
            long modTime = modifTime / 1000; // seconds
            long ims = request.getDateHeader(HEADER_IF_MODIFIED_SINCE) / 1000;
            return modTime <= ims;
        }

        // we have no modification time value, assume modified
        return false;
    }

    /**
     * @param resource
     * @param request
     * @param response
     * @param servletContext 
     * @throws RepositoryException
     */
    private void setHeaders(Map<String, Object> properties, Resource resource, HttpServletResponse response,
            String alternativeStream, ServletContext servletContext) {

        long modifTime = StorageClientUtils.toLong(
                properties.get(StorageClientUtils.getAltField(Content.LASTMODIFIED_FIELD, alternativeStream)));
        if (modifTime > 0) {
            response.setDateHeader(HEADER_LAST_MODIFIED, modifTime);
        }

        String contentType = (String) properties
                .get(StorageClientUtils.getAltField(Content.MIMETYPE_FIELD, alternativeStream));
        if (contentType == null && servletContext != null) {
            final String ct = servletContext.getMimeType(resource.getPath());
            if (ct != null) {
                contentType = ct;
            }
        }
        if (contentType != null) {
            response.setContentType(contentType);
        }

        String encoding = (String) properties
                .get(StorageClientUtils.getAltField(Content.ENCODING_FIELD, alternativeStream));
        if (encoding != null) {
            response.setCharacterEncoding(encoding);
        }
    }

    /**
     * Set the <code>Content-Length</code> header to the give value. If the length is larger
     * than <code>Integer.MAX_VALUE</code> it is converted to a string and the
     * <code>setHeader(String, String)</code> method is called instead of the
     * <code>setContentLength(int)</code> method.
     *
     * @param response
     *          The response on which to set the <code>Content-Length</code> header.
     * @param length
     *          The content length to be set. If this value is equal to or less than zero,
     *          the header is not set.
     */
    private void setContentLength(Map<String, Object> properties, HttpServletResponse response,
            String alternativeStream) {
        long length = StorageClientUtils
                .toLong(properties.get(StorageClientUtils.getAltField(Content.LENGTH_FIELD, alternativeStream)));
        if (length > 0) {
            if (length < Integer.MAX_VALUE) {
                response.setContentLength((int) length);
            } else {
                response.setHeader("Content-Length", String.valueOf(length));
            }
        }
    }

}