Example usage for javax.servlet.http HttpServletRequest getDateHeader

List of usage examples for javax.servlet.http HttpServletRequest getDateHeader

Introduction

In this page you can find the example usage for javax.servlet.http HttpServletRequest getDateHeader.

Prototype

public long getDateHeader(String name);

Source Link

Document

Returns the value of the specified request header as a long value that represents a Date object.

Usage

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

private void handleCopyBlob(HttpServletRequest request, HttpServletResponse response, InputStream is,
        BlobStore blobStore, String destContainerName, String destBlobName) throws IOException, S3Exception {
    String copySourceHeader = request.getHeader("x-amz-copy-source");
    copySourceHeader = URLDecoder.decode(copySourceHeader, "UTF-8");
    if (copySourceHeader.startsWith("/")) {
        // Some clients like boto do not include the leading slash
        copySourceHeader = copySourceHeader.substring(1);
    }/* w  w  w  .  jav  a2 s  . c om*/
    String[] path = copySourceHeader.split("/", 2);
    if (path.length != 2) {
        throw new S3Exception(S3ErrorCode.INVALID_REQUEST);
    }
    String sourceContainerName = path[0];
    String sourceBlobName = path[1];
    boolean replaceMetadata = "REPLACE".equalsIgnoreCase(request.getHeader("x-amz-metadata-directive"));

    if (sourceContainerName.equals(destContainerName) && sourceBlobName.equals(destBlobName)
            && !replaceMetadata) {
        throw new S3Exception(S3ErrorCode.INVALID_REQUEST);
    }

    CopyOptions.Builder options = CopyOptions.builder();

    String ifMatch = request.getHeader("x-amz-copy-source-if-match");
    if (ifMatch != null) {
        options.ifMatch(ifMatch);
    }
    String ifNoneMatch = request.getHeader("x-amz-copy-source-if-none-match");
    if (ifNoneMatch != null) {
        options.ifNoneMatch(ifNoneMatch);
    }
    long ifModifiedSince = request.getDateHeader("x-amz-copy-source-if-modified-since");
    if (ifModifiedSince != -1) {
        options.ifModifiedSince(new Date(ifModifiedSince));
    }
    long ifUnmodifiedSince = request.getDateHeader("x-amz-copy-source-if-unmodified-since");
    if (ifUnmodifiedSince != -1) {
        options.ifUnmodifiedSince(new Date(ifUnmodifiedSince));
    }

    if (replaceMetadata) {
        ContentMetadataBuilder contentMetadata = ContentMetadataBuilder.create();
        ImmutableMap.Builder<String, String> userMetadata = ImmutableMap.builder();
        for (String headerName : Collections.list(request.getHeaderNames())) {
            String headerValue = Strings.nullToEmpty(request.getHeader(headerName));
            if (headerName.equalsIgnoreCase(HttpHeaders.CACHE_CONTROL)) {
                contentMetadata.cacheControl(headerValue);
            } else if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_DISPOSITION)) {
                contentMetadata.contentDisposition(headerValue);
            } else if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_ENCODING)) {
                contentMetadata.contentEncoding(headerValue);
            } else if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_LANGUAGE)) {
                contentMetadata.contentLanguage(headerValue);
            } else if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_TYPE)) {
                contentMetadata.contentType(headerValue);
            } else if (startsWithIgnoreCase(headerName, USER_METADATA_PREFIX)) {
                userMetadata.put(headerName.substring(USER_METADATA_PREFIX.length()), headerValue);
            }
            // TODO: Expires
        }
        options.contentMetadata(contentMetadata.build());
        options.userMetadata(userMetadata.build());
    }

    String eTag;
    try {
        eTag = blobStore.copyBlob(sourceContainerName, sourceBlobName, destContainerName, destBlobName,
                options.build());
    } catch (KeyNotFoundException knfe) {
        throw new S3Exception(S3ErrorCode.NO_SUCH_KEY, knfe);
    }

    // TODO: jclouds should include this in CopyOptions
    String cannedAcl = request.getHeader("x-amz-acl");
    if (cannedAcl != null && !cannedAcl.equalsIgnoreCase("private")) {
        handleSetBlobAcl(request, response, is, blobStore, destContainerName, destBlobName);
    }

    BlobMetadata blobMetadata = blobStore.blobMetadata(destContainerName, destBlobName);
    try (Writer writer = response.getWriter()) {
        XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(writer);
        xml.writeStartDocument();
        xml.writeStartElement("CopyObjectResult");
        xml.writeDefaultNamespace(AWS_XMLNS);

        writeSimpleElement(xml, "LastModified", formatDate(blobMetadata.getLastModified()));
        writeSimpleElement(xml, "ETag", maybeQuoteETag(eTag));

        xml.writeEndElement();
        xml.flush();
    } catch (XMLStreamException xse) {
        throw new IOException(xse);
    }
}

From source file:axiom.servlet.AbstractServletClient.java

/**
 * Handle a request.//from  w  ww  .ja va 2s . co  m
 *
 * @param request ...
 * @param response ...
 *
 * @throws ServletException ...
 * @throws IOException ...
 */
protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    final String httpMethod = request.getMethod();
    if (!"POST".equalsIgnoreCase(httpMethod) && !"GET".equalsIgnoreCase(httpMethod)) {
        sendError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                "HTTP Method " + httpMethod + " not supported.");
        return;
    }

    RequestTrans reqtrans = new RequestTrans(request, response, getPathInfo(request));

    try {
        // get the character encoding
        String encoding = request.getCharacterEncoding();

        if (encoding == null) {
            // no encoding from request, use the application's charset
            encoding = getApplication().getCharset();
        }

        // read and set http parameters
        parseParameters(request, reqtrans, encoding);

        List uploads = null;
        ServletRequestContext reqcx = new ServletRequestContext(request);

        if (ServletFileUpload.isMultipartContent(reqcx)) {
            // get session for upload progress monitoring
            UploadStatus uploadStatus = getApplication().getUploadStatus(reqtrans);
            try {
                uploads = parseUploads(reqcx, reqtrans, uploadStatus, encoding);
            } catch (Exception upx) {
                System.err.println("Error in file upload: " + upx);
                if (uploadSoftfail) {
                    String msg = upx.getMessage();
                    if (msg == null || msg.length() == 0) {
                        msg = upx.toString();
                    }
                    reqtrans.set("axiom_upload_error", msg);
                } else if (upx instanceof FileUploadBase.SizeLimitExceededException) {
                    sendError(response, HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
                            "File upload size exceeds limit of " + uploadLimit + "kB");
                    return;
                } else {
                    sendError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                            "Error in file upload: " + upx);
                    return;
                }
            }
        }

        parseCookies(request, reqtrans, encoding);

        // do standard HTTP variables
        String host = request.getHeader("Host");

        if (host != null) {
            host = host.toLowerCase();
            reqtrans.set("http_host", host);
        }

        String referer = request.getHeader("Referer");

        if (referer != null) {
            reqtrans.set("http_referer", referer);
        }

        try {
            long ifModifiedSince = request.getDateHeader("If-Modified-Since");

            if (ifModifiedSince > -1) {
                reqtrans.setIfModifiedSince(ifModifiedSince);
            }
        } catch (IllegalArgumentException ignore) {
        }

        String ifNoneMatch = request.getHeader("If-None-Match");

        if (ifNoneMatch != null) {
            reqtrans.setETags(ifNoneMatch);
        }

        String remotehost = request.getRemoteAddr();

        if (remotehost != null) {
            reqtrans.set("http_remotehost", remotehost);
        }

        // get the cookie domain to use for this response, if any.
        String resCookieDomain = cookieDomain;

        if (resCookieDomain != null) {
            // check if cookieDomain is valid for this response.
            // (note: cookieDomain is guaranteed to be lower case)
            // check for x-forwarded-for header, fix for bug 443
            String proxiedHost = request.getHeader("x-forwarded-host");
            if (proxiedHost != null) {
                if (proxiedHost.toLowerCase().indexOf(cookieDomain) == -1) {
                    resCookieDomain = null;
                }
            } else if ((host != null) && host.toLowerCase().indexOf(cookieDomain) == -1) {
                resCookieDomain = null;
            }
        }

        // check if session cookie is present and valid, creating it if not.
        checkSessionCookie(request, response, reqtrans, resCookieDomain);

        String browser = request.getHeader("User-Agent");

        if (browser != null) {
            reqtrans.set("http_browser", browser);
        }

        String language = request.getHeader("Accept-Language");

        if (language != null) {
            reqtrans.set("http_language", language);
        }

        String authorization = request.getHeader("authorization");

        if (authorization != null) {
            reqtrans.set("authorization", authorization);
        }

        ResponseTrans restrans = getApplication().execute(reqtrans);

        // if the response was already written and committed by the application
        // we can skip this part and return
        if (response.isCommitted()) {
            return;
        }

        // set cookies
        if (restrans.countCookies() > 0) {
            CookieTrans[] resCookies = restrans.getCookies();

            for (int i = 0; i < resCookies.length; i++)
                try {
                    Cookie c = resCookies[i].getCookie("/", resCookieDomain);

                    response.addCookie(c);
                } catch (Exception ignore) {
                    ignore.printStackTrace();
                }
        }

        // write response
        writeResponse(request, response, reqtrans, restrans);

    } catch (Exception x) {
        try {
            if (debug) {
                sendError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Server error: " + x);
                x.printStackTrace();
            } else {
                sendError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                        "The server encountered an error while processing your request. "
                                + "Please check back later.");
            }

            log("Exception in execute: " + x);
        } catch (IOException io_e) {
            log("Exception in sendError: " + io_e);
        }
    }
}

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

/**
 * Process the actual request./*from w w w .  j  av a 2s.  com*/
 *
 * @param request
 *            The request to be processed.
 * @param response
 *            The response to be created.
 * @param content
 *            Whether the request body should be written (GET) or not
 *            (HEAD).
 * @throws IOException
 *             If something fails at I/O level.
 *
 * @author BalusC
 * @link
 *       http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and
 *       .html
 */
private void processStaticRequest(File file, HttpServletRequest request, HttpServletResponse response,
        boolean content) throws IOException {
    // Validate the requested file
    // ------------------------------------------------------------

    if (file == null) {
        // Get requested file by path info.
        String requestedFile = request.getPathInfo();

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

        // URL-decode the file name (might contain spaces and on) and
        // prepare
        // file object.
        file = new File(rootFolder, URLDecoder.decode(requestedFile, "UTF-8"));
    }
    // Check if file actually exists in filesystem.
    if (!file.exists()) {
        // Do your thing if the file appears to be non-existing.
        // Throw an exception, or send 404, or show default/warning page, or
        // just ignore it.
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            if (content) {
                // Copy single part range.
                copy(input, output, r.start, r.length);
            }

        } else {

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

            if (content) {
                // Cast back to ServletOutputStream to get the easy println
                // methods.
                ServletOutputStream sos = (ServletOutputStream) output;

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

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

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

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

public boolean browserCacheIsValid(HttpServletRequest request, Long lastModified, String currentETag) {

    try {//from www  .j  a  v  a2  s  .  c o  m
        // Handle If-None-Match
        String browserETagsStr = (String) request.getHeader("If-None-Match");
        if (browserETagsStr != null) {
            Iterator<String> browserETags = WGUtils
                    .deserializeCollection(browserETagsStr, ",", true, new Character('"')).iterator();
            while (browserETags.hasNext()) {
                String rawETag = (String) browserETags.next();
                if (rawETag.trim().equals("*")) {
                    return true;
                }

                int startETag = rawETag.indexOf('"');
                int endETag = rawETag.lastIndexOf('"');
                if (startETag != -1 && endETag != -1 && startETag != endETag) {
                    String eTag = rawETag.substring(startETag + 1, endETag);
                    if (eTag.equals(currentETag)) {
                        return true;
                    }
                }
            }
        }

        // Handle If-Modified-Since
        if (lastModified != null) {
            long modSince = request.getDateHeader("If-Modified-Since");
            if (modSince != -1 && modSince >= WGUtils.cutoffTimeMillis(lastModified)) {
                return true;
            }
        }

    } catch (Exception e) {
        getCore().getLog().error("Exception evaluating browser cache HTTP headers", e);
    }

    return false;

}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            if (content) {
                // Copy single part range.
                copy(input, output, r.start, r.length);
            }

        } else {

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

            if (content) {
                // Cast back to ServletOutputStream to get the easy println
                // methods.
                ServletOutputStream sos = (ServletOutputStream) output;

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

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

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

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

public final void doHandle(HttpServletRequest baseRequest, HttpServletRequest request,
        HttpServletResponse response, InputStream is) throws IOException, S3Exception {
    String method = request.getMethod();
    String uri = request.getRequestURI();

    if (!this.servicePath.isEmpty()) {
        if (uri.length() > this.servicePath.length()) {
            uri = uri.substring(this.servicePath.length());
        }/*from   w ww  .  j a va2  s.com*/
    }

    logger.debug("request: {}", request);
    String hostHeader = request.getHeader(HttpHeaders.HOST);
    if (hostHeader != null && virtualHost.isPresent()) {
        hostHeader = HostAndPort.fromString(hostHeader).getHostText();
        String virtualHostSuffix = "." + virtualHost.get();
        if (!hostHeader.equals(virtualHost.get())) {
            if (hostHeader.endsWith(virtualHostSuffix)) {
                String bucket = hostHeader.substring(0, hostHeader.length() - virtualHostSuffix.length());
                uri = "/" + bucket + uri;
            } else {
                String bucket = hostHeader.toLowerCase();
                uri = "/" + bucket + uri;
            }
        }
    }

    boolean hasDateHeader = false;
    boolean hasXAmzDateHeader = false;
    for (String headerName : Collections.list(request.getHeaderNames())) {
        for (String headerValue : Collections.list(request.getHeaders(headerName))) {
            logger.trace("header: {}: {}", headerName, Strings.nullToEmpty(headerValue));
        }
        if (headerName.equalsIgnoreCase(HttpHeaders.DATE)) {
            hasDateHeader = true;
        } else if (headerName.equalsIgnoreCase("x-amz-date")) {
            hasXAmzDateHeader = true;
        }
    }

    // when access information is not provided in request header,
    // treat it as anonymous, return all public accessible information
    if (!anonymousIdentity && (method.equals("GET") || method.equals("HEAD") || method.equals("POST"))
            && request.getHeader(HttpHeaders.AUTHORIZATION) == null
            && request.getParameter("X-Amz-Algorithm") == null && request.getParameter("AWSAccessKeyId") == null
            && defaultBlobStore != null) {
        doHandleAnonymous(request, response, is, uri, defaultBlobStore);
        return;
    }

    if (!anonymousIdentity && !hasDateHeader && !hasXAmzDateHeader && request.getParameter("X-Amz-Date") == null
            && request.getParameter("Expires") == null) {
        throw new S3Exception(S3ErrorCode.ACCESS_DENIED,
                "AWS authentication requires a valid Date or" + " x-amz-date header");
    }

    // TODO: apply sanity checks to X-Amz-Date
    if (hasDateHeader) {
        long date;
        try {
            date = request.getDateHeader(HttpHeaders.DATE);
        } catch (IllegalArgumentException iae) {
            throw new S3Exception(S3ErrorCode.ACCESS_DENIED, iae);
        }
        if (date < 0) {
            throw new S3Exception(S3ErrorCode.ACCESS_DENIED);
        }
        long now = System.currentTimeMillis();
        if (now + TimeUnit.DAYS.toMillis(1) < date || now - TimeUnit.DAYS.toMillis(1) > date) {
            throw new S3Exception(S3ErrorCode.REQUEST_TIME_TOO_SKEWED);
        }
    }

    BlobStore blobStore;
    String requestIdentity = null;
    String headerAuthorization = request.getHeader(HttpHeaders.AUTHORIZATION);
    S3AuthorizationHeader authHeader = null;
    boolean presignedUrl = false;

    if (!anonymousIdentity) {
        if (headerAuthorization == null) {
            String algorithm = request.getParameter("X-Amz-Algorithm");
            if (algorithm == null) {
                String identity = request.getParameter("AWSAccessKeyId");
                String signature = request.getParameter("Signature");
                if (identity == null || signature == null) {
                    throw new S3Exception(S3ErrorCode.ACCESS_DENIED);
                }
                headerAuthorization = "AWS " + identity + ":" + signature;
                presignedUrl = true;
            } else if (algorithm.equals("AWS4-HMAC-SHA256")) {
                String credential = request.getParameter("X-Amz-Credential");
                String signedHeaders = request.getParameter("X-Amz-SignedHeaders");
                String signature = request.getParameter("X-Amz-Signature");
                if (credential == null || signedHeaders == null || signature == null) {
                    throw new S3Exception(S3ErrorCode.ACCESS_DENIED);
                }
                headerAuthorization = "AWS4-HMAC-SHA256" + " Credential=" + credential
                        + ", requestSignedHeaders=" + signedHeaders + ", Signature=" + signature;
                presignedUrl = true;
            }
        }

        try {
            authHeader = new S3AuthorizationHeader(headerAuthorization);
        } catch (IllegalArgumentException iae) {
            throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT, iae);
        }
        requestIdentity = authHeader.identity;
    }

    String[] path = uri.split("/", 3);
    for (int i = 0; i < path.length; i++) {
        path[i] = URLDecoder.decode(path[i], "UTF-8");
    }

    Map.Entry<String, BlobStore> provider = blobStoreLocator.locateBlobStore(requestIdentity,
            path.length > 1 ? path[1] : null, path.length > 2 ? path[2] : null);
    if (anonymousIdentity) {
        blobStore = provider.getValue();
        String contentSha256 = request.getHeader("x-amz-content-sha256");
        if ("STREAMING-AWS4-HMAC-SHA256-PAYLOAD".equals(contentSha256)) {
            is = new ChunkedInputStream(is);
        }
    } else if (requestIdentity == null) {
        throw new S3Exception(S3ErrorCode.ACCESS_DENIED);
    } else {
        if (provider == null) {
            throw new S3Exception(S3ErrorCode.INVALID_ACCESS_KEY_ID);
        }

        String credential = provider.getKey();
        blobStore = provider.getValue();

        String expiresString = request.getParameter("Expires");
        if (expiresString != null) {
            long expires = Long.parseLong(expiresString);
            long nowSeconds = System.currentTimeMillis() / 1000;
            if (nowSeconds >= expires) {
                throw new S3Exception(S3ErrorCode.ACCESS_DENIED);
            }
        }

        String dateString = request.getParameter("X-Amz-Date");
        expiresString = request.getParameter("X-Amz-Expires");
        if (dateString != null && expiresString != null) {
            long date = parseIso8601(dateString);
            long expires = Long.parseLong(expiresString);
            long nowSeconds = System.currentTimeMillis() / 1000;
            if (nowSeconds >= date + expires) {
                throw new S3Exception(S3ErrorCode.ACCESS_DENIED, "Request has expired");
            }
        }

        switch (authHeader.authenticationType) {
        case AWS_V2:
            switch (authenticationType) {
            case AWS_V2:
            case AWS_V2_OR_V4:
            case NONE:
                break;
            default:
                throw new S3Exception(S3ErrorCode.ACCESS_DENIED);
            }
            break;
        case AWS_V4:
            switch (authenticationType) {
            case AWS_V4:
            case AWS_V2_OR_V4:
            case NONE:
                break;
            default:
                throw new S3Exception(S3ErrorCode.ACCESS_DENIED);
            }
            break;
        case NONE:
            break;
        default:
            throw new IllegalArgumentException("Unhandled type: " + authHeader.authenticationType);
        }

        String expectedSignature = null;

        // When presigned url is generated, it doesn't consider service path
        String uriForSigning = presignedUrl ? uri : this.servicePath + uri;
        if (authHeader.hmacAlgorithm == null) {
            expectedSignature = createAuthorizationSignature(request, uriForSigning, credential);
        } else {
            String contentSha256 = request.getHeader("x-amz-content-sha256");
            try {
                byte[] payload;
                if (request.getParameter("X-Amz-Algorithm") != null) {
                    payload = new byte[0];
                } else if ("STREAMING-AWS4-HMAC-SHA256-PAYLOAD".equals(contentSha256)) {
                    payload = new byte[0];
                    is = new ChunkedInputStream(is);
                } else if ("UNSIGNED-PAYLOAD".equals(contentSha256)) {
                    payload = new byte[0];
                } else {
                    // buffer the entire stream to calculate digest
                    payload = ByteStreams.toByteArray(ByteStreams.limit(is, v4MaxNonChunkedRequestSize + 1));
                    if (payload.length == v4MaxNonChunkedRequestSize + 1) {
                        throw new S3Exception(S3ErrorCode.MAX_MESSAGE_LENGTH_EXCEEDED);
                    }
                    is = new ByteArrayInputStream(payload);
                }
                expectedSignature = createAuthorizationSignatureV4(baseRequest, authHeader, payload,
                        uriForSigning, credential);
            } catch (InvalidKeyException | NoSuchAlgorithmException e) {
                throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT, e);
            }
        }

        if (!expectedSignature.equals(authHeader.signature)) {
            logger.debug("fail to validate signature");
            throw new S3Exception(S3ErrorCode.SIGNATURE_DOES_NOT_MATCH);
        }
    }

    for (String parameter : Collections.list(request.getParameterNames())) {
        if (UNSUPPORTED_PARAMETERS.contains(parameter)) {
            logger.error("Unknown parameters {} with URI {}", parameter, request.getRequestURI());
            throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
        }
    }

    // emit NotImplemented for unknown x-amz- headers
    for (String headerName : Collections.list(request.getHeaderNames())) {
        if (ignoreUnknownHeaders) {
            continue;
        }
        if (!headerName.startsWith("x-amz-")) {
            continue;
        }
        if (headerName.startsWith("x-amz-meta-")) {
            continue;
        }
        if (!SUPPORTED_X_AMZ_HEADERS.contains(headerName.toLowerCase())) {
            logger.error("Unknown header {} with URI {}", headerName, request.getRequestURI());
            throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
        }
    }

    String uploadId = request.getParameter("uploadId");
    switch (method) {
    case "DELETE":
        if (path.length <= 2 || path[2].isEmpty()) {
            handleContainerDelete(response, blobStore, path[1]);
            return;
        } else if (uploadId != null) {
            handleAbortMultipartUpload(response, blobStore, path[1], path[2], uploadId);
            return;
        } else {
            handleBlobRemove(response, blobStore, path[1], path[2]);
            return;
        }
    case "GET":
        if (uri.equals("/")) {
            handleContainerList(response, blobStore);
            return;
        } else if (path.length <= 2 || path[2].isEmpty()) {
            if ("".equals(request.getParameter("acl"))) {
                handleGetContainerAcl(response, blobStore, path[1]);
                return;
            } else if ("".equals(request.getParameter("location"))) {
                handleContainerLocation(response, blobStore, path[1]);
                return;
            } else if ("".equals(request.getParameter("uploads"))) {
                handleListMultipartUploads(request, response, blobStore, path[1]);
                return;
            }
            handleBlobList(request, response, blobStore, path[1]);
            return;
        } else {
            if ("".equals(request.getParameter("acl"))) {
                handleGetBlobAcl(response, blobStore, path[1], path[2]);
                return;
            } else if (uploadId != null) {
                handleListParts(request, response, blobStore, path[1], path[2], uploadId);
                return;
            }
            handleGetBlob(request, response, blobStore, path[1], path[2]);
            return;
        }
    case "HEAD":
        if (path.length <= 2 || path[2].isEmpty()) {
            handleContainerExists(blobStore, path[1]);
            return;
        } else {
            handleBlobMetadata(request, response, blobStore, path[1], path[2]);
            return;
        }
    case "POST":
        if ("".equals(request.getParameter("delete"))) {
            handleMultiBlobRemove(response, is, blobStore, path[1]);
            return;
        } else if ("".equals(request.getParameter("uploads"))) {
            handleInitiateMultipartUpload(request, response, blobStore, path[1], path[2]);
            return;
        } else if (uploadId != null && request.getParameter("partNumber") == null) {
            handleCompleteMultipartUpload(response, is, blobStore, path[1], path[2], uploadId);
            return;
        }
        break;
    case "PUT":
        if (path.length <= 2 || path[2].isEmpty()) {
            if ("".equals(request.getParameter("acl"))) {
                handleSetContainerAcl(request, response, is, blobStore, path[1]);
                return;
            }
            handleContainerCreate(request, response, is, blobStore, path[1]);
            return;
        } else if (uploadId != null) {
            if (request.getHeader("x-amz-copy-source") != null) {
                handleCopyPart(request, response, blobStore, path[1], path[2], uploadId);
            } else {
                handleUploadPart(request, response, is, blobStore, path[1], path[2], uploadId);
            }
            return;
        } else if (request.getHeader("x-amz-copy-source") != null) {
            handleCopyBlob(request, response, is, blobStore, path[1], path[2]);
            return;
        } else {
            if ("".equals(request.getParameter("acl"))) {
                handleSetBlobAcl(request, response, is, blobStore, path[1], path[2]);
                return;
            }
            handlePutBlob(request, response, is, blobStore, path[1], path[2]);
            return;
        }
    default:
        break;
    }
    logger.error("Unknown method {} with URI {}", method, request.getRequestURI());
    throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
}

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

private void handleCopyPart(HttpServletRequest request, HttpServletResponse response, BlobStore blobStore,
        String containerName, String blobName, String uploadId) throws IOException, S3Exception {
    // TODO: duplicated from handlePutBlob
    String copySourceHeader = request.getHeader("x-amz-copy-source");
    copySourceHeader = URLDecoder.decode(copySourceHeader, "UTF-8");
    if (copySourceHeader.startsWith("/")) {
        // Some clients like boto do not include the leading slash
        copySourceHeader = copySourceHeader.substring(1);
    }// w  ww.ja  va2s  . c  o  m
    String[] path = copySourceHeader.split("/", 2);
    if (path.length != 2) {
        throw new S3Exception(S3ErrorCode.INVALID_REQUEST);
    }
    String sourceContainerName = path[0];
    String sourceBlobName = path[1];

    GetOptions options = new GetOptions();
    String range = request.getHeader("x-amz-copy-source-range");
    if (range != null && range.startsWith("bytes=") &&
    // ignore multiple ranges
            range.indexOf(',') == -1) {
        range = range.substring("bytes=".length());
        String[] ranges = range.split("-", 2);
        if (ranges[0].isEmpty()) {
            options.tail(Long.parseLong(ranges[1]));
        } else if (ranges[1].isEmpty()) {
            options.startAt(Long.parseLong(ranges[0]));
        } else {
            options.range(Long.parseLong(ranges[0]), Long.parseLong(ranges[1]));
        }
    }

    String partNumberString = request.getParameter("partNumber");
    if (partNumberString == null) {
        throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT);
    }
    int partNumber;
    try {
        partNumber = Integer.parseInt(partNumberString);
    } catch (NumberFormatException nfe) {
        throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT,
                "Part number must be an integer between 1 and 10000" + ", inclusive", nfe,
                ImmutableMap.of("ArgumentName", "partNumber", "ArgumentValue", partNumberString));
    }
    if (partNumber < 1 || partNumber > 10_000) {
        throw new S3Exception(S3ErrorCode.INVALID_ARGUMENT,
                "Part number must be an integer between 1 and 10000" + ", inclusive", (Throwable) null,
                ImmutableMap.of("ArgumentName", "partNumber", "ArgumentValue", partNumberString));
    }

    // TODO: how to reconstruct original mpu?
    MultipartUpload mpu = MultipartUpload.create(containerName, blobName, uploadId,
            createFakeBlobMetadata(blobStore), new PutOptions());

    Blob blob = blobStore.getBlob(sourceContainerName, sourceBlobName, options);
    if (blob == null) {
        throw new S3Exception(S3ErrorCode.NO_SUCH_KEY);
    }

    BlobMetadata blobMetadata = blob.getMetadata();

    String ifMatch = request.getHeader("x-amz-copy-source-if-match");
    String ifNoneMatch = request.getHeader("x-amz-copy-source-if-modified-since");
    long ifModifiedSince = request.getDateHeader("x-amz-copy-source-if-none-match");
    long ifUnmodifiedSince = request.getDateHeader("x-amz-copy-source-if-unmodified-since");
    String eTag = blobMetadata.getETag();
    if (eTag != null) {
        eTag = maybeQuoteETag(eTag);
        if (ifMatch != null && !ifMatch.equals(eTag)) {
            throw new S3Exception(S3ErrorCode.PRECONDITION_FAILED);
        }
        if (ifNoneMatch != null && ifNoneMatch.equals(eTag)) {
            throw new S3Exception(S3ErrorCode.PRECONDITION_FAILED);
        }
    }

    Date lastModified = blobMetadata.getLastModified();
    if (lastModified != null) {
        if (ifModifiedSince != -1 && lastModified.compareTo(new Date(ifModifiedSince)) <= 0) {
            throw new S3Exception(S3ErrorCode.PRECONDITION_FAILED);
        }
        if (ifUnmodifiedSince != -1 && lastModified.compareTo(new Date(ifUnmodifiedSince)) >= 0) {
            throw new S3Exception(S3ErrorCode.PRECONDITION_FAILED);
        }
    }

    long contentLength = blobMetadata.getContentMetadata().getContentLength();

    String blobStoreType = getBlobStoreType(blobStore);
    try (InputStream is = blob.getPayload().openStream()) {
        if (blobStoreType.equals("azureblob")) {
            // Azure has a maximum part size of 4 MB while S3 has a minimum
            // part size of 5 MB and a maximum of 5 GB.  Split a single S3
            // part multiple Azure parts.
            long azureMaximumMultipartPartSize = blobStore.getMaximumMultipartPartSize();
            HashingInputStream his = new HashingInputStream(Hashing.md5(), is);
            for (int offset = 0, subPartNumber = 0; offset < contentLength; offset += azureMaximumMultipartPartSize, ++subPartNumber) {
                Payload payload = Payloads.newInputStreamPayload(
                        new UncloseableInputStream(ByteStreams.limit(his, azureMaximumMultipartPartSize)));
                payload.getContentMetadata()
                        .setContentLength(Math.min(azureMaximumMultipartPartSize, contentLength - offset));
                blobStore.uploadMultipartPart(mpu, 10_000 * partNumber + subPartNumber, payload);
            }
            eTag = BaseEncoding.base16().lowerCase().encode(his.hash().asBytes());
        } else {
            Payload payload = Payloads.newInputStreamPayload(is);
            payload.getContentMetadata().setContentLength(contentLength);

            MultipartPart part = blobStore.uploadMultipartPart(mpu, partNumber, payload);
            eTag = part.partETag();
        }
    }

    try (Writer writer = response.getWriter()) {
        XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(writer);
        xml.writeStartDocument();
        xml.writeStartElement("CopyObjectResult");
        xml.writeDefaultNamespace(AWS_XMLNS);

        writeSimpleElement(xml, "LastModified", formatDate(lastModified));
        if (eTag != null) {
            writeSimpleElement(xml, "ETag", maybeQuoteETag(eTag));
        }

        xml.writeEndElement();
        xml.flush();
    } catch (XMLStreamException xse) {
        throw new IOException(xse);
    }
}

From source file:edu.ucsd.library.dams.api.FileStoreServlet.java

/**
 * Process the actual request.//  ww w.  ja  v a2 s. c  om
 * @param request The request to be processed.
 * @param response The response to be created.
 * @param content Whether the request body should be written (GET) or not
 *  (HEAD).
 * @throws IOException If something fails at I/O level.
 */
private void processRequest(HttpServletRequest request, HttpServletResponse response, boolean content)
        throws IOException {
    // Validate the requested file -------------------------------------

    // Get requested file by path info.
    /* start ucsd changes */

    // get object and file ids from path
    String objid = null;
    String cmpid = null;
    String fileid = null;
    try {
        // /bb1234567x/1.tif
        // /bb1234567x/1/2.tif
        String[] path = request.getPathInfo().split("/");
        if (path.length == 3) {
            objid = path[1];
            fileid = path[2];
        } else if (path.length == 4) {
            objid = path[1];
            cmpid = path[2];
            fileid = path[3];
        }
    } catch (Exception e) {
        String errorMessage = "Error parsing request pathInfo: " + request.getPathInfo();
        log.error(errorMessage, e);
        response.setContentType("text/plain");
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMessage);
        return;
    }

    // make sure required parameters are populated
    if (objid == null || objid.trim().length() == 0 || fileid == null || fileid.trim().length() == 0) {
        response.setContentType("text/plain");
        response.sendError(HttpServletResponse.SC_BAD_REQUEST,
                "Subject and file must be specified in the request URI");
        return;
    }
    String fullFilename = objid + (StringUtils.isNotBlank(cmpid) ? "-" + cmpid : "") + "-" + fileid;

    // first load the FileStore (no point if this doesn't work)
    FileStore fs = null;
    long fsTime = 0;
    try {
        long start = System.currentTimeMillis();
        fs = FileStoreUtil.getFileStore(props, fsDefault);
        fsTime = System.currentTimeMillis() - start;
    } catch (Exception ex) {
        response.setContentType("text/plain");
        response.sendError(response.SC_INTERNAL_SERVER_ERROR, "Error initializing FileStore");
        ex.printStackTrace();
        return;
    }

    // check authorization attribute
    String restricted = null;
    String authorized = (String) request.getAttribute("edu.ucsd.library.dams.api.DAMSAPIServlet.authorized");
    if (authorized == null || !authorized.equals("true")) {
        log.warn("Illegal Access from IP " + request.getRemoteAddr() + " for file " + fullFilename);
        response.setContentType("text/plain");
        response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access without authorization.");
        return;
    } else {
        log.info("DAMS Access authorized for IP " + request.getRemoteAddr() + " for file " + fullFilename);
        restricted = (String) request.getAttribute("pas.restricted");
        //Disable browser caching for restricted objects.
        if (restricted != null && restricted.equals("1")) {
            String browser = request.getHeader("User-Agent");
            if (browser != null && browser.indexOf("MSIE") != -1) {
                response.addHeader("Cache-Control", "post-check=0, pre-check=0");
            } else {
                response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
            }
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Expires", "0");
        }
    }
    /* end ucsd changes */

    // load file metadata
    Map<String, String> meta = null;
    long metaTime = 0;
    try {
        long start = System.currentTimeMillis();
        meta = fs.meta(objid, cmpid, fileid);
        metaTime = System.currentTimeMillis() - start;
    } catch (Exception ex) {
        log.error("File " + fullFilename + " doesn't exist.", ex);
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }

    // Prepare some variables. The ETag is an unique identifier of the file
    String length = meta.get("Content-Length");
    String lastModStr = meta.get("Last-Modified");
    long lastModified = 0L;
    try {
        lastModified = df.parse(lastModStr).getTime();
    } catch (Exception ex) {
        // error parsing lastmod date... set to now
        lastModified = System.currentTimeMillis();
    }
    String eTag = meta.get("ETag");
    if (eTag == null) {
        eTag = fullFilename + "_" + length + "_" + lastModified;
    }

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

    // If-None-Match header should contain "*" or ETag. If so, return 304.
    String ifNoneMatch = request.getHeader("If-None-Match");
    if (ifNoneMatch != null && matches(ifNoneMatch, eTag)) {
        response.setHeader("ETag", eTag); // Required in 304.
        response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
        return;
    }

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

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

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

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

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

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

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

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

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

    String sFileName = request.getParameter("name");
    if (sFileName == null || (sFileName = sFileName.trim()).length() == 0)
        sFileName = fullFilename;

    // Initialize response.
    response.reset();
    response.setBufferSize(DEFAULT_BUFFER_SIZE);
    response.setHeader("Content-Disposition", disposition + ";filename=\"" + sFileName + "\"");
    response.setHeader("ETag", eTag);
    response.setDateHeader("Last-Modified", lastModified);
    /* begin ucsd changes */
    if (restricted == null || !restricted.equals("1")) {
        response.setDateHeader("Expires", System.currentTimeMillis() + DEFAULT_EXPIRE_TIME);
    }
    /* end ucsd changes */

    // Send requested file to client ------------------------------------

    // Prepare streams.
    InputStream input = null;
    OutputStream output = null;
    long fileTime = 0;
    if (content) {
        try {
            long start = System.currentTimeMillis();
            // Open streams.
            input = fs.getInputStream(objid, cmpid, fileid);
            output = response.getOutputStream();
            response.setContentType(contentType);
            if (acceptsGzip) {
                // The browser accepts GZIP, so GZIP the content.
                response.setHeader("Content-Encoding", "gzip");
                output = new GZIPOutputStream(output, DEFAULT_BUFFER_SIZE);
            } else {
                // Content length is not directly predictable in case of
                // GZIP. So only add it if there is no means of GZIP, else
                // browser will hang.
                response.setHeader("Content-Length", length);
            }

            // Copy full range.
            /* begin ucsd changes */
            FileStoreUtil.copy(input, output);
            fileTime = System.currentTimeMillis() - start;
            /* begin ucsd changes */
        } catch (Exception ex) {
            log.error("Error reading " + fullFilename, ex);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } finally {
            /* begin ucsd changes */
            log.info("Time in miliseconds to retrival file " + fullFilename + "(" + length + " bytes)"
                    + ": Total " + (fsTime + metaTime + fileTime) + "[FileStore initiation: " + fsTime
                    + "; Metadata query: " + metaTime + "; File download: " + fileTime + "]");
            /* begin ucsd changes */
            // Gently close streams.
            close(output);
            close(input);
        }
    }
}

From source file:org.jpublish.servlet.JPublishServlet.java

/**
 * Called when the HTTP request method is POST.  This method provides the
 * main control logic.//from   ww  w .j ava 2 s  . c  om
 *
 * @param request  The HTTP request
 * @param response The HTTP response
 * @throws ServletException
 * @throws IOException
 */

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    ServletContext servletContext = getServletContext();

    String pathInfo = request.getPathInfo();
    if (log.isDebugEnabled())
        log.debug("Path info: " + pathInfo);

    //OLAT: PATCH BEGIN
    if (pathInfo == null) {
        // we have a direct mapping rule in web.xml like /kurs/bridge.html -> jpublish servlet
        // so we use servletPath
        //String servletPath = request.getServletPath();
        pathInfo = request.getServletPath();
    } //TODO: make more generic (use JPublish with other servlets..) and post it.

    if (log.isDebugEnabled())
        log.debug("calculated Path info: " + pathInfo);
    //OLAT: PATCH END

    String contextPath = request.getContextPath();

    if (log.isDebugEnabled())
        log.debug("Context path: " + contextPath);

    // get the real path
    String path = getRealPath(pathInfo);

    if (siteContext.getPathDispatcherManager().canDispatch(path)) {

        //only one from below ones should react
        String dispatcherName = siteContext.getPathDispatcherManager().canForwardDispatch(path);

        if (dispatcherName != null) {
            siteContext.getPathDispatcherManager().forward(request, response, dispatcherName);
        }

        dispatcherName = siteContext.getPathDispatcherManager().canIncludeDispatch(path);
        if (dispatcherName != null) {
            siteContext.getPathDispatcherManager().include(request, response, dispatcherName);
        }

        return;
    }

    if (log.isDebugEnabled())
        log.debug("Real path: " + path);

    // create the session if enabled
    HttpSession session = null;

    if (isSessionEnabled(path)) {
        session = request.getSession(true);
    }

    // get the character encoding map
    CharacterEncodingMap characterEncodingMap = siteContext.getCharacterEncodingManager().getMap(path);

    // set the request character encoding for parameter data
    if (requireVersion(2, 3)) {
        request.setCharacterEncoding(characterEncodingMap.getRequestEncoding());
    }

    // put standard servlet stuff into the context
    JPublishContext context = new JPublishContext(this);
    context.put("request", request);
    context.put("response", response);
    context.put("session", session);
    context.put("application", servletContext);

    // add the character encoding map to the context
    context.put("characterEncodingMap", characterEncodingMap);

    // add the URLUtilities to the context
    URLUtilities urlUtilities = new URLUtilities(request, response);
    context.put("urlUtilities", urlUtilities);
    // deprecated
    context.put("url_util", urlUtilities);
    context.put("url_utils", urlUtilities);

    // add the DateUtilities to the context
    context.put("dateUtilities", DateUtilities.getInstance());

    // add the NumberUtilities to the context
    context.put("numberUtilities", NumberUtilities.getInstance());

    // add the messages log to the context
    context.put("syslog", SiteContext.syslog);

    // expose the SiteContext
    context.put("site", siteContext);

    // expose the context itself for debugging purposes
    if (siteContext.isDebug()) {
        context.put("context", context);
    }

    // switch from merge to eval, while rendering Velocity templates [hack for utf8]
    if (siteContext.isEval()) {
        context.put("evaluateVelocityTemplates", "true");
    }

    if (siteContext.isProtectReservedNames()) {
        context.enableCheckReservedNames(this);
    }

    // add the repositories to the context
    Iterator repositories = siteContext.getRepositories().iterator();
    while (repositories.hasNext()) {
        Repository repository = (Repository) repositories.next();
        if (log.isDebugEnabled())
            log.debug("Adding " + repository.getClass().getName() + " as " + repository.getName());

        context.put(repository.getName(), new RepositoryWrapper(repository, context));
    }

    Writer out = null;
    try {

        if (executePreEvaluationActions(request, response, context, path))
            return;

        if (context.getStopProcessing() != null) {
            return;
        }

        // if the page is static
        StaticResourceManager staticResourceManager = siteContext.getStaticResourceManager();

        if (staticResourceManager.resourceExists(path)) {

            long ifModifiedSince = request.getDateHeader(HEADER_IF_MODIFIED);
            // will round the file's lastModified down to the nearest second by dividing by 1000 and then
            // multiplying it by 1000; florin
            long lastUpdatedTime = -1;
            try {
                lastUpdatedTime = (staticResourceManager.getLastModified(path) / 1000) * 1000;
            } catch (Exception e) {
                log.warn("Cannot read the LastModified for: " + path);
            }
            //log.info(String.format("%s: if modified since: %d, file time:%d, modified? %s", path, ifModifiedSince, lastUpdatedTime, (ifModifiedSince < lastUpdatedTime)));

            if (ifModifiedSince < lastUpdatedTime) {
                // execute the global actions
                if (executeGlobalActions(request, response, context, path))
                    return;

                if (context.getStopProcessing() != null)
                    return;

                // execute path actions
                if (executePathActions(request, response, context, path))
                    return;
                if (context.getStopProcessing() != null)
                    return;

                // execute parameter actions
                if (executeParameterActions(request, response, context, path))
                    return;
                if (context.getStopProcessing() != null)
                    return;

                // load and return the static resource
                setResponseContentType(request, response, path, characterEncodingMap);
                response.setDateHeader(HEADER_LAST_MODIFIED, lastUpdatedTime);
                response.setContentLength((int) staticResourceManager.getContentLength(path));
                try {
                    staticResourceManager.load(path, response.getOutputStream());
                } catch (SocketException e) {
                    log.warn("Error writing to output stream: " + e.getMessage());
                }
                // OLAT: PATCH: Ignore org.apache.catalina.connector.ClientAbortException
                // that is produced by InternetExplorer (6.0) browser caching.
                catch (IOException e) {
                    if (e instanceof FileNotFoundException) {
                        throw e;
                    }
                }
            } else {
                //If the browser has current version of the file, don't send it. Just say it has not changed
                response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            }
            return;
        } else {
            if (log.isDebugEnabled())
                log.debug("Static resource '" + path + "' not found");
        }

        // load the page
        if (log.isDebugEnabled())
            log.debug("Loading the page.");

        PageInstance pageInstance = siteContext.getPageManager().getPage(path);
        Page page = new Page(pageInstance);

        context.disableCheckReservedNames(this);

        // expose the page in the context
        context.put("page", page);

        // expose components in the context
        context.put("components", new ComponentMap(context));

        if (siteContext.isProtectReservedNames()) {
            context.enableCheckReservedNames(this);
        }

        request.setAttribute(JPUBLISH_CONTEXT, context);

        // execute the global actions
        if (executeGlobalActions(request, response, context, path))
            return;
        if (context.getStopProcessing() != null)
            return;

        // execute path actions
        if (executePathActions(request, response, context, path))
            return;
        if (context.getStopProcessing() != null)
            return;

        // execute parameter actions
        if (executeParameterActions(request, response, context, path))
            return;
        if (context.getStopProcessing() != null)
            return;

        // execute the page actions
        if (log.isDebugEnabled())
            log.debug("Executing page actions.");

        if (optionalRedirect(page.executeActions(context), path, response))
            return;
        if (context.getStopProcessing() != null) {
            return;
        }
        setResponseContentType(request, response, path, characterEncodingMap);

        // get the template
        // OLAT: PATCH using context.getPage() instead of page object
        // since page can be changed in internal forward and page points
        // still to the original page
        Template template = siteContext.getTemplateManager()
                .getTemplate(context.getPage().getFullTemplateName());

        // get the Servlet writer
        out = response.getWriter();

        // merge the template
        if (log.isDebugEnabled())
            log.debug("Merging with template " + template.getPath());
        // OLAT: PATCH using context.getPage() instead of page object
        // since page can be changed in internal forward and page points
        // still to the original page
        template.merge(context, context.getPage(), out);

    } catch (FileNotFoundException e) {
        log.error("[404] " + path);
        if (!response.isCommitted()) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, path);
        }
    } catch (Exception e) {
        // Allow Jetty RequestRetry exception to propogate to container!
        if ("org.mortbay.jetty.RetryRequest".equals(e.getClass().getName())) {
            throw (RuntimeException) e;
        }

        JPublishError error = new JPublishError(e, context);
        Iterator errorHandlers = siteContext.getErrorHandlers(path).iterator();
        while (errorHandlers.hasNext()) {
            ((ErrorHandler) errorHandlers.next()).handleError(error);
        }

        if (!error.isConsumed()) {
            log.error("Execution error: " + MessageUtilities.format(e.getMessage()));
            if (!response.isCommitted()) {
                throw new ServletException(e);
            }
        }
    } finally {
        try {
            executePostEvaluationActions(request, response, context, path);
        } catch (Exception e) {
            log.error("Error executing post evaluation actions: " + MessageUtilities.format(e.getMessage()));
        }
    }
}