Author: ieb Date: Fri Aug 12 11:58:06 2016 New Revision: 1756169 URL: http://svn.apache.org/viewvc?rev=1756169&view=rev Log: SLING-5948 Support Streaming - Cleaned up headers, added more javadoc, incorporated feedback from RTC
Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/ParameterSupport.java sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/StreamedUploadOperation.java Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/ParameterSupport.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/ParameterSupport.java?rev=1756169&r1=1756168&r2=1756169&view=diff ============================================================================== --- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/ParameterSupport.java (original) +++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/ParameterSupport.java Fri Aug 12 11:58:06 2016 @@ -70,6 +70,15 @@ public class ParameterSupport { /** Content type signaling parameters in request body */ private static final String WWW_FORM_URL_ENC = "application/x-www-form-urlencoded"; + /** name of the header used to identify an upload mode */ + public static final String SLING_UPLOADMODE_HEADER = "Sling-uploadmode"; + /** name of the parameter used to identify upload mode */ + public static final String UPLOADMODE_PARAM = "uploadmode"; + /** request attribute that stores the parts iterator when streaming */ + public static final String REQUEST_PARTS_ITERATOR_ATTRIBUTE = "request-parts-iterator"; + /** value of upload mode header/parameter indicating streaming is requested */ + public static final String STREAM_UPLOAD = "stream"; + /** default log */ private final Logger log = LoggerFactory.getLogger(getClass()); @@ -284,7 +293,7 @@ public class ParameterSupport { if (isStreamed(parameters, this.getServletRequest())) { // special case, the request is Mutipart and streamed processing has been requested try { - this.getServletRequest().setAttribute("request-parts-iterator", new RequestPartsIterator(this.getServletRequest())); + this.getServletRequest().setAttribute(REQUEST_PARTS_ITERATOR_ATTRIBUTE, new RequestPartsIterator(this.getServletRequest())); this.log.debug("getRequestParameterMapInternal: Iterator<javax.servlet.http.Part> available as request attribute named request-parts-iterator"); } catch (IOException e) { this.log.error("getRequestParameterMapInternal: Error parsing mulmultipart streamed requesttipart streamed request", e); @@ -326,11 +335,11 @@ public class ParameterSupport { * @return true if the request was made with streaming in mind. */ private boolean isStreamed(ParameterMap parameters, HttpServletRequest servletRequest) { - if ( "stream".equals(servletRequest.getHeader("X-uploadmode") ) ) { + if ( STREAM_UPLOAD.equals(servletRequest.getHeader(SLING_UPLOADMODE_HEADER)) ) { return true; } - RequestParameter[] rp = parameters.get("uploadmode"); - return ( rp != null && rp.length == 1 && "stream".equals(rp[0].getString())); + RequestParameter[] rp = parameters.get(UPLOADMODE_PARAM); + return ( rp != null && rp.length == 1 && STREAM_UPLOAD.equals(rp[0].getString())); } private void getContainerParameters(final ParameterMap parameters, final String encoding, final boolean alwaysAdd) { Modified: sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java?rev=1756169&r1=1756168&r2=1756169&view=diff ============================================================================== --- sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java (original) +++ sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java Fri Aug 12 11:58:06 2016 @@ -36,10 +36,22 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +/** + * Contains a Lazy iterator of Parts from the request stream loaded as the request is streamed using the Commons FileUpload API. + */ public class RequestPartsIterator implements Iterator<Part> { private static final Logger LOG = LoggerFactory.getLogger(RequestPartsIterator.class); + + /** The CommonsFile Upload streaming API iterator */ private final FileItemIterator itemIterator; + /** + * Create and initialse the iterator using the request. The request must be fresh. Headers can have been read but the stream + * must not have been parsed. + * @param servletRequest the request + * @throws IOException when there is a problem reading the request. + * @throws FileUploadException when there is a problem parsing the request. + */ public RequestPartsIterator(HttpServletRequest servletRequest) throws IOException, FileUploadException { ServletFileUpload upload = new ServletFileUpload(); itemIterator = upload.getItemIterator(servletRequest); @@ -69,6 +81,9 @@ public class RequestPartsIterator implem return null; } + /** + * Internal implementation of the Part API from Servlet 3 wrapping the Commons File Upload FIleItemStream object. + */ private static class StreamedRequestPart implements Part { private final FileItemStream fileItem; private final InputStream inputStream; Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/StreamedUploadOperation.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/StreamedUploadOperation.java?rev=1756169&r1=1756168&r2=1756169&view=diff ============================================================================== --- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/StreamedUploadOperation.java (original) +++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/StreamedUploadOperation.java Fri Aug 12 11:58:06 2016 @@ -71,6 +71,13 @@ public class StreamedUploadOperation ext } + /** + * Check the request and return true if there is a parts iterator attribute present. This attribute + * will have been put there by the Sling Engine ParameterSupport class. If its not present, the request + * is not streamed and cant be processed by this class. Check this first before using this class. + * @param request the request. + * @return true if the request can be streamed. + */ public boolean isRequestStreamed(SlingHttpServletRequest request) { return request.getAttribute("request-parts-iterator") != null; } @@ -108,6 +115,12 @@ public class StreamedUploadOperation ext } + /** + * Add a field to the store of formFields. + * @param formFields the formFileds + * @param name the name of the field. + * @param part the part. + */ private void addField(Map<String, List<String>> formFields, String name, Part part) { List<String> values = formFields.get(name); if ( values == null ) { @@ -122,6 +135,17 @@ public class StreamedUploadOperation ext } + /** + * Write content to the resource API creating a standard JCR structure of nt:file - nt:resource - jcr:data. + * This method will commit to the repository to force the repository to read from the input stream and write + * to the target. How efficient that is depends on the repository implementation. + * @param resolver the resource resolver. + * @param part the part containing the file body. + * @param formFields form fields collected so far. + * @param response the response object, updated by the operation. + * @param changes changes made to the repo. + * @throws PersistenceException + */ private void writeContent(final ResourceResolver resolver, final Part part, final Map<String, List<String>> formFields, @@ -172,10 +196,20 @@ public class StreamedUploadOperation ext } } + /** + * Is the part a form field ? + * @param part + * @return + */ private boolean isFormField(Part part) { return (part.getSubmittedFileName() == null); } + /** + * Get the upload file name from the part. + * @param part + * @return + */ private String getUploadName(Part part) { String name = part.getSubmittedFileName(); // strip of possible path (some browsers include the entire path) @@ -184,12 +218,21 @@ public class StreamedUploadOperation ext return Text.escapeIllegalJcrChars(name); } + /** + * Does the resource exist ? + * @param resource + * @return + */ private boolean resourceExists(final Resource resource) { return (resource != null && !ResourceUtil.isSyntheticResource(resource)); } - + /** + * Get the content type of the part. + * @param part + * @return + */ private String getContentType(final Part part) { String contentType = part.getContentType(); if (contentType != null) {