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