List of usage examples for javax.servlet.http HttpServletRequest getDateHeader
public long getDateHeader(String name);
long
value that represents a Date
object. 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())); } } }