Author: ieb
Date: Fri Aug 12 11:57:30 2016
New Revision: 1756166

URL: http://svn.apache.org/viewvc?rev=1756166&view=rev
Log:
SLING-5948 Support Streaming - Implementation of proposal 1 using a 
Interator<Part>

Added:
    
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java
   (with props)
Modified:
    
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/ParameterSupport.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=1756166&r1=1756165&r2=1756166&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:57:30 2016
@@ -281,10 +281,27 @@ public class ParameterSupport {
 
                 // Multipart POST
                 if (ServletFileUpload.isMultipartContent(new 
ServletRequestContext(this.getServletRequest()))) {
-                    this.parseMultiPartPost(parameters);
-                    this.requestDataUsed = true;
-                    addContainerParameters = checkForAdditionalParameters;
-                    useFallback = false;
+                    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.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);
+                        } catch (FileUploadException e) {
+                            this.log.error("getRequestParameterMapInternal: 
Error parsing mulmultipart streamed request", e);
+                        }
+                        // The request data has been passed to the 
RequestPartsIterator, hence from a RequestParameter pov its been used, and must 
not be used again.
+                        this.requestDataUsed = true;
+                        // must not try and get anything from the request at 
this point so avoid jumping through the stream.
+                        addContainerParameters = false;
+                        useFallback = false;
+                    } else {
+                        this.parseMultiPartPost(parameters);
+                        this.requestDataUsed = true;
+                        addContainerParameters = checkForAdditionalParameters;
+                        useFallback = false;
+                    }
                 }
             }
             if ( useFallback ) {
@@ -300,6 +317,22 @@ public class ParameterSupport {
         return this.postParameterMap;
     }
 
+
+    /**
+     * Checks to see if there is an upload mode header or uploadmode parameter 
indicating the request is
+     * to be streamed from the client to the server.
+     * @param parameters parameters processed from the query string only.
+     * @param servletRequest the servlet request, where the body has not been 
processed.
+     * @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") ) ) {
+            return true;
+        }
+        RequestParameter[] rp = parameters.get("uploadmode");
+        return ( rp != null && rp.length == 1 && 
"stream".equals(rp[0].getString()));
+    }
+
     private void getContainerParameters(final ParameterMap parameters, final 
String encoding, final boolean alwaysAdd) {
         final Map<?, ?> pMap = getServletRequest().getParameterMap();
         for (Map.Entry<?, ?> entry : pMap.entrySet()) {
@@ -368,4 +401,6 @@ public class ParameterSupport {
         }
     }
 
+
+
 }
\ No newline at end of file

Added: 
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=1756166&view=auto
==============================================================================
--- 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java
 (added)
+++ 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java
 Fri Aug 12 11:57:30 2016
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.engine.impl.parameters;
+
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileItemStream;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+
+public class RequestPartsIterator implements Iterator<Part> {
+    private static final Logger LOG = 
LoggerFactory.getLogger(RequestPartsIterator.class);
+    private final FileItemIterator itemIterator;
+
+    public RequestPartsIterator(HttpServletRequest servletRequest) throws 
IOException, FileUploadException {
+        ServletFileUpload upload = new ServletFileUpload();
+        itemIterator = upload.getItemIterator(servletRequest);
+    }
+
+    @Override
+    public boolean hasNext() {
+        try {
+            return itemIterator.hasNext();
+        } catch (FileUploadException e) {
+            LOG.error("hasNext Item failed cause:" + e.getMessage(), e);
+        } catch (IOException e) {
+            LOG.error("hasNext Item failed cause:" + e.getMessage(), e);
+        }
+        return false;
+    }
+
+    @Override
+    public Part next() {
+        try {
+            return new StreamedRequestPart(itemIterator.next());
+        } catch (IOException e) {
+            LOG.error("next Item failed cause:" + e.getMessage(), e);
+        } catch (FileUploadException e) {
+            LOG.error("next Item failed cause:" + e.getMessage(), e);
+        }
+        return null;
+    }
+
+    private static class StreamedRequestPart implements Part {
+        private final FileItemStream fileItem;
+        private final InputStream inputStream;
+
+        public StreamedRequestPart(FileItemStream fileItem) throws IOException 
{
+            this.fileItem = fileItem;
+            inputStream = fileItem.openStream();
+        }
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            return inputStream;
+        }
+
+        @Override
+        public String getContentType() {
+            return fileItem.getContentType();
+        }
+
+        @Override
+        public String getName() {
+            return fileItem.getName();
+        }
+
+        @Override
+        public long getSize() {
+            return 0;
+        }
+
+        @Override
+        public void write(String s) throws IOException {
+            throw new UnsupportedOperationException("Writing parts directly to 
disk is not supported by this implementation, use getInputStream instead");
+        }
+
+        @Override
+        public void delete() throws IOException {
+            // no underlying storage is used, so nothing to delete.
+        }
+
+        @Override
+        public String getHeader(String headerName) {
+            return fileItem.getHeaders().getHeader(headerName);
+        }
+
+        @Override
+        public Collection<String> getHeaders(String headerName) {
+            return toCollection(fileItem.getHeaders().getHeaders(headerName));
+        }
+
+
+        @Override
+        public Collection<String> getHeaderNames() {
+            return toCollection(fileItem.getHeaders().getHeaderNames());
+        }
+
+        @Override
+        public String getSubmittedFileName() {
+            return fileItem.getFieldName();
+        }
+
+        private <T> Collection<T> toCollection(Iterator<T> i) {
+            if ( i == null ) {
+                return Collections.emptyList();
+            } else {
+                List<T> c = new ArrayList<T>();
+                while(i.hasNext()) {
+                    c.add(i.next());
+                }
+                return c;
+            }
+        }
+
+    }
+}

Propchange: 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/RequestPartsIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to