Author: nbelaevski
Date: 2011-04-21 08:19:14 -0400 (Thu, 21 Apr 2011)
New Revision: 22436
Added:
trunk/ui/input/api/src/main/java/org/richfaces/exception/
trunk/ui/input/api/src/main/java/org/richfaces/exception/FileUploadException.java
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadExternalContextFactory.java
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadFacesContextFactory.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/BaseMultipartRequest.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/BaseUploadedFile.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadDiscResource.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadMemoryResource.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadParam.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadResource.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadValueParam.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequest25.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequestParser.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/ProgressControl.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/ProgressServletInputStream.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/UploadedFile25.java
Removed:
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadPartialViewContextFactory.java
trunk/ui/input/ui/src/main/java/org/richfaces/exception/FileUploadException.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileParam.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/Param.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/ValueParam.java
Modified:
trunk/ui/input/api/src/main/java/org/richfaces/model/UploadedFile.java
trunk/ui/input/ui/src/main/java/org/richfaces/renderkit/FileUploadRendererBase.java
trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequest.java
trunk/ui/input/ui/src/main/java/org/richfaces/resource/FileUploadProgressResource.java
trunk/ui/input/ui/src/main/resources/META-INF/fileupload.faces-config.xml
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/fileupload.js
Log:
Copied: trunk/ui/input/api/src/main/java/org/richfaces/exception/FileUploadException.java
(from rev 22426,
trunk/ui/input/ui/src/main/java/org/richfaces/exception/FileUploadException.java)
===================================================================
--- trunk/ui/input/api/src/main/java/org/richfaces/exception/FileUploadException.java
(rev 0)
+++
trunk/ui/input/api/src/main/java/org/richfaces/exception/FileUploadException.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright ${year}, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.exception;
+
+import javax.faces.FacesException;
+
+
+/**
+ * Thrown when an exception occurs while uploading a file.
+ *
+ */
+public class FileUploadException extends FacesException {
+
+ private static final long serialVersionUID = -3579917878909990838L;
+
+ public FileUploadException() {
+ this(null, null);
+ }
+
+ public FileUploadException(String message) {
+ this(message, null);
+ }
+
+ public FileUploadException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
Modified: trunk/ui/input/api/src/main/java/org/richfaces/model/UploadedFile.java
===================================================================
--- trunk/ui/input/api/src/main/java/org/richfaces/model/UploadedFile.java 2011-04-21
12:16:50 UTC (rev 22435)
+++ trunk/ui/input/api/src/main/java/org/richfaces/model/UploadedFile.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -21,16 +21,36 @@
*/
package org.richfaces.model;
+import java.io.IOException;
import java.io.InputStream;
+import java.util.Collection;
+import org.richfaces.exception.FileUploadException;
+
/**
* @author Konstantin Mishin
*
*/
public interface UploadedFile {
String getContentType();
- byte[] getData();
- InputStream getInputStream();
+
+ byte[] getData() throws FileUploadException;
+
+ InputStream getInputStream() throws IOException;
+
String getName();
+
long getSize();
+
+ void delete() throws IOException;
+
+ void write(String fileName) throws IOException;
+
+ String getHeader(String headerName);
+
+ Collection<String> getHeaderNames();
+
+ Collection<String> getHeaders(String headerName);
+
+ String getParameterName();
}
Added:
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadExternalContextFactory.java
===================================================================
---
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadExternalContextFactory.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadExternalContextFactory.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,228 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.context;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.AbstractMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.faces.FacesException;
+import javax.faces.FacesWrapper;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.ExternalContextFactory;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.richfaces.exception.FileUploadException;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+import org.richfaces.model.UploadedFile;
+import org.richfaces.request.MultipartRequest;
+import org.richfaces.request.MultipartRequest.ResponseState;
+import org.richfaces.request.MultipartRequest25;
+import org.richfaces.request.MultipartRequestParser;
+import org.richfaces.request.ProgressControl;
+
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Lists;
+
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class FileUploadExternalContextFactory extends ExternalContextFactory implements
FacesWrapper<ExternalContextFactory> {
+
+ private static class HttpSessionMap extends AbstractMap<String, Object> {
+
+ private HttpSession session;
+
+ public HttpSessionMap(HttpSession session) {
+ super();
+ this.session = session;
+ }
+
+ @Override
+ public Object get(Object key) {
+ return session.getAttribute((String) key);
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ session.setAttribute(key, value);
+ return null;
+ }
+
+ @Override
+ public Object remove(Object key) {
+ session.removeAttribute((String) key);
+ return null;
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<String, Object>> entrySet() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public static final String UID_KEY = "rf_fu_uid";
+
+ private static final Logger LOGGER = RichfacesLogger.CONTEXT.getLogger();
+
+ private static final Pattern AMPERSAND = Pattern.compile("&+");
+
+ private ExternalContextFactory wrappedFactory;
+
+ public FileUploadExternalContextFactory(ExternalContextFactory wrappedFactory) {
+ super();
+
+ //TODO Use ConfigurationServiceHelper to initialize InitParameters.
+ this.wrappedFactory = wrappedFactory;
+ }
+
+ @Override
+ public ExternalContextFactory getWrapped() {
+ return wrappedFactory;
+ }
+
+ private String getParameterValueFromQueryString(String queryString, String paramName)
{
+ if (queryString != null) {
+ String[] nvPairs = AMPERSAND.split(queryString);
+ for (String nvPair : nvPairs) {
+ if (nvPair.length() == 0) {
+ continue;
+ }
+
+ int eqIdx = nvPair.indexOf('=');
+ if (eqIdx >= 0) {
+ try {
+ String name = URLDecoder.decode(nvPair.substring(0, eqIdx),
"UTF-8");
+
+ if (paramName.equals(name)) {
+ return URLDecoder.decode(nvPair.substring(eqIdx + 1),
"UTF-8");
+ }
+ } catch (UnsupportedEncodingException e) {
+ // log warning and skip this parameter
+ LOGGER.debug(e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private boolean isCreateTempFiles(ServletContext servletContext) {
+ String param =
servletContext.getInitParameter("org.richfaces.fileUpload.createTempFiles");
+ if (param != null) {
+ return Boolean.parseBoolean(param);
+ }
+
+ return true;
+ }
+
+ private String getTempFilesDirectory(ServletContext servletContext) {
+ String result =
servletContext.getInitParameter("org.richfaces.fileUpload.tempFilesDirectory");
+ if (result == null) {
+ File servletTempDir = (File)
servletContext.getAttribute("javax.servlet.context.tempdir");
+ if (servletTempDir != null) {
+ result = servletTempDir.getAbsolutePath();
+ }
+ }
+ if (result == null) {
+ result = new
File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
+ }
+
+ return result;
+ }
+
+ private long getMaxRequestSize(ServletContext servletContext) {
+ String param =
servletContext.getInitParameter("org.richfaces.fileUpload.maxRequestSize");
+ if (param != null) {
+ return Long.parseLong(param);
+ }
+
+ return 0;
+ }
+
+ @Override
+ public ExternalContext getExternalContext(Object context, Object request, Object
response) throws FacesException {
+ Object wrappedRequest = request;
+
+ if (wrappedRequest instanceof HttpServletRequest) {
+ HttpServletRequest httpRequest = (HttpServletRequest) wrappedRequest;
+
+ if (httpRequest.getContentType() != null &&
httpRequest.getContentType().startsWith("multipart/")) {
+ String uid =
getParameterValueFromQueryString(httpRequest.getQueryString(), UID_KEY);
+
+ if (uid != null) {
+ long contentLength =
Long.parseLong(httpRequest.getHeader("Content-Length"));
+
+ Map<String,Object> contextMap = new
HttpSessionMap(httpRequest.getSession());
+
+ ProgressControl progressControl = new ProgressControl(contextMap,
uid, contentLength);
+
+ wrappedRequest = wrapMultipartRequestServlet25((ServletContext)
context, httpRequest, uid,
+ contentLength, progressControl);
+ }
+ }
+ }
+
+ return getWrapped().getExternalContext(context, wrappedRequest, response);
+ }
+
+ private MultipartRequest wrapMultipartRequestServlet25(ServletContext servletContext,
HttpServletRequest request,
+ String uploadId, long contentLength, ProgressControl progressControl) {
+
+ MultipartRequest multipartRequest;
+
+ long maxRequestSize = getMaxRequestSize(servletContext);
+ if (maxRequestSize == 0 || contentLength <= maxRequestSize) {
+ MultipartRequestParser requestParser = new MultipartRequestParser(request,
isCreateTempFiles(servletContext),
+ getTempFilesDirectory(servletContext), progressControl);
+
+ ResponseState result = ResponseState.ok;
+
+ try {
+ requestParser.parse();
+ } catch (FileUploadException e) {
+ result = ResponseState.serverError;
+ }
+
+ multipartRequest = new MultipartRequest25(request, uploadId, progressControl,
requestParser.getParameters(),
+ requestParser.getUploadedFiles(), result);
+ } else {
+ multipartRequest = new MultipartRequest25(request, uploadId, progressControl,
LinkedListMultimap.<String, String>create(),
+ Lists.<UploadedFile>newArrayList(), ResponseState.sizeExceeded);
+ }
+
+ request.setAttribute(MultipartRequest.REQUEST_ATTRIBUTE_NAME, multipartRequest);
+
+ return multipartRequest;
+ }
+
+}
\ No newline at end of file
Added:
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadFacesContextFactory.java
===================================================================
---
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadFacesContextFactory.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadFacesContextFactory.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,119 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.context;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.faces.FacesException;
+import javax.faces.FacesWrapper;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.FacesContextFactory;
+import javax.faces.context.FacesContextWrapper;
+import javax.faces.lifecycle.Lifecycle;
+import javax.servlet.http.HttpServletResponse;
+
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+import org.richfaces.request.MultipartRequest;
+import org.richfaces.request.MultipartRequest.ResponseState;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class FileUploadFacesContextFactory extends FacesContextFactory implements
FacesWrapper<FacesContextFactory> {
+
+ private static final Logger LOGGER = RichfacesLogger.CONTEXT.getLogger();
+
+ private static final class FileUploadFacesContext extends FacesContextWrapper {
+
+ private FacesContext facesContext;
+
+ public FileUploadFacesContext(FacesContext facesContext) {
+ super();
+ this.facesContext = facesContext;
+ }
+
+ @Override
+ public FacesContext getWrapped() {
+ return facesContext;
+ }
+
+ @Override
+ public void release() {
+ MultipartRequest multipartRequest = (MultipartRequest)
getExternalContext().getRequestMap().get(MultipartRequest.REQUEST_ATTRIBUTE_NAME);
+
+ if (multipartRequest != null) {
+ multipartRequest.release();
+ }
+
+ super.release();
+ }
+ }
+
+ private FacesContextFactory wrappedFactory;
+
+ public FileUploadFacesContextFactory(FacesContextFactory wrappedFactory) {
+ super();
+ this.wrappedFactory = wrappedFactory;
+ }
+
+ @Override
+ public FacesContextFactory getWrapped() {
+ return wrappedFactory;
+ }
+
+ @Override
+ public FacesContext getFacesContext(Object context, Object request, Object response,
Lifecycle lifecycle)
+ throws FacesException {
+
+ FacesContext facesContext = wrappedFactory.getFacesContext(context, request,
response, lifecycle);
+
+ MultipartRequest multipartRequest = (MultipartRequest)
facesContext.getExternalContext().getRequestMap().get(MultipartRequest.REQUEST_ATTRIBUTE_NAME);
+ if (multipartRequest != null) {
+ facesContext = new FileUploadFacesContext(facesContext);
+
+ if (multipartRequest.getResponseState() != ResponseState.ok) {
+ printResponse(facesContext, multipartRequest);
+ }
+ }
+
+ return facesContext;
+ }
+
+
+ private void printResponse(FacesContext facesContext, MultipartRequest
multipartRequest) {
+ facesContext.responseComplete();
+ ExternalContext externalContext = facesContext.getExternalContext();
+ externalContext.setResponseStatus(HttpServletResponse.SC_OK);
+ externalContext.setResponseContentType("text/html");
+ try {
+ Writer writer = externalContext.getResponseOutputWriter();
+ writer.write("<html id=\"" +
FileUploadExternalContextFactory.UID_KEY + multipartRequest.getUploadId() + ":"
+ multipartRequest.getResponseState() + "\"/>");
+ writer.close();
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+}
Deleted:
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadPartialViewContextFactory.java
===================================================================
---
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadPartialViewContextFactory.java 2011-04-21
12:16:50 UTC (rev 22435)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/context/FileUploadPartialViewContextFactory.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -1,194 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright ${year}, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.richfaces.context;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.net.URLDecoder;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.faces.context.PartialViewContext;
-import javax.faces.context.PartialViewContextFactory;
-import javax.faces.context.PartialViewContextWrapper;
-import javax.faces.event.PhaseId;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.richfaces.exception.FileUploadException;
-import org.richfaces.log.Logger;
-import org.richfaces.log.RichfacesLogger;
-import org.richfaces.request.MultipartRequest;
-
-/**
- * @author Konstantin Mishin
- *
- */
-public class FileUploadPartialViewContextFactory extends PartialViewContextFactory {
-
- public static final String UID_KEY = "rf_fu_uid";
-
- public static final String UID_ALT_KEY = "rf_fu_uid_alt";
-
- private static enum ResponseState {
- sizeExceeded, stopped, serverError
- };
-
- private static final Logger LOGGER = RichfacesLogger.CONTEXT.getLogger();
-
- private static final Pattern AMPERSAND = Pattern.compile("&+");
-
- private PartialViewContextFactory parentFactory;
-
- /** Flag indicating whether a temporary file should be used to cache the uploaded
file */
- private boolean createTempFiles = true;
-
- private String tempFilesDirectory;
-
- /** The maximum size of a file upload request. 0 means no limit. */
- private long maxRequestSize = 0;
-
- public FileUploadPartialViewContextFactory(PartialViewContextFactory parentFactory)
{
- this.parentFactory = parentFactory;
- ExternalContext context =
FacesContext.getCurrentInstance().getExternalContext();
- //TODO Use ConfigurationServiceHelper to initialize InitParameters.
- String param =
context.getInitParameter("org.richfaces.fileUpload.createTempFiles");
- if (param != null) {
- this.createTempFiles = Boolean.parseBoolean(param);
- }
- this.tempFilesDirectory =
context.getInitParameter("org.richfaces.fileUpload.tempFilesDirectory");
- param =
context.getInitParameter("org.richfaces.fileUpload.maxRequestSize");
- if (param != null) {
- this.maxRequestSize = Long.parseLong(param);
- }
- }
-
- @Override
- public PartialViewContext getPartialViewContext(FacesContext facesContext) {
- PartialViewContext partialViewContext =
parentFactory.getPartialViewContext(facesContext);
- ExternalContext externalContext = facesContext.getExternalContext();
- Object request = externalContext.getRequest();
- if (request instanceof HttpServletRequest) {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- Map<String, String> queryParamMap =
parseQueryString(httpRequest.getQueryString());
- String uid = queryParamMap.get(UID_KEY);
- if (uid != null) {
- long contentLength =
Long.parseLong(externalContext.getRequestHeaderMap().get("Content-Length"));
- if (maxRequestSize != 0 && contentLength > maxRequestSize) {
- printResponse(facesContext, uid, ResponseState.sizeExceeded);
- } else {
- final MultipartRequest multipartRequest =
- new MultipartRequest(httpRequest, createTempFiles,
tempFilesDirectory, uid);
- try {
- final PartialViewContext viewContext = partialViewContext;
- partialViewContext = new PartialViewContextWrapper() {
- @Override
- public void processPartial(PhaseId phaseId) {
- try {
- super.processPartial(phaseId);
- } finally {
- if (PhaseId.RENDER_RESPONSE.equals(phaseId)) {
- multipartRequest.cancel();
- // TODO PartialViewContext.release isn't
invoked by JSF. Maybe it's a bug.
- // So we should use
PartialViewContext.processPartial instead of.
- }
- }
- }
-
- // TODO This method can be removed from here when
PartialViewContextWrapper will implement
- // it.
- @Override
- public void setPartialRequest(boolean isPartialRequest) {
- viewContext.setPartialRequest(isPartialRequest);
- }
-
- @Override
- public PartialViewContext getWrapped() {
- return viewContext;
- }
- };
- multipartRequest.parseRequest();
- if (!multipartRequest.isDone()) {
- printResponse(facesContext, uid, ResponseState.stopped);
- } else {
- externalContext.setRequest(multipartRequest);
- }
- } catch (FileUploadException e) {
- printResponse(facesContext, uid, ResponseState.serverError);
- } finally {
- multipartRequest.clearRequestData();
- }
- }
- }
- }
- return partialViewContext;
- }
-
- private Map<String, String> parseQueryString(String queryString) {
- if (queryString != null) {
- Map<String, String> parameters = new HashMap<String, String>();
- String[] nvPairs = AMPERSAND.split(queryString);
- for (String nvPair : nvPairs) {
- if (nvPair.length() == 0) {
- continue;
- }
-
- int eqIdx = nvPair.indexOf('=');
- if (eqIdx >= 0) {
- try {
- String name = URLDecoder.decode(nvPair.substring(0, eqIdx),
"UTF-8");
- if (!parameters.containsKey(name)) {
- String value = URLDecoder.decode(nvPair.substring(eqIdx + 1),
"UTF-8");
-
- parameters.put(name, value);
- }
- } catch (UnsupportedEncodingException e) {
- // log warning and skip this parameter
- LOGGER.warn(e.getLocalizedMessage(), e);
- }
- }
- }
- return parameters;
- } else {
- return Collections.emptyMap();
- }
- }
-
- private void printResponse(FacesContext facesContext, String uid, ResponseState
state) {
- facesContext.responseComplete();
- ExternalContext externalContext = facesContext.getExternalContext();
- externalContext.setResponseStatus(HttpServletResponse.SC_OK);
- externalContext.setResponseContentType(MultipartRequest.TEXT_HTML);
- try {
- Writer writer = externalContext.getResponseOutputWriter();
- writer.write("<html id=\"" + UID_KEY + uid + ":"
+ state + "\"/>");
- writer.close();
- } catch (IOException e) {
- LOGGER.error(e);
- }
- }
-}
Deleted: trunk/ui/input/ui/src/main/java/org/richfaces/exception/FileUploadException.java
===================================================================
---
trunk/ui/input/ui/src/main/java/org/richfaces/exception/FileUploadException.java 2011-04-21
12:16:50 UTC (rev 22435)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/exception/FileUploadException.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -1,43 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright ${year}, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.richfaces.exception;
-
-/**
- * Thrown when an exception occurs while uploading a file.
- *
- */
-public class FileUploadException extends RuntimeException {
-
- private static final long serialVersionUID = -3579917878909990838L;
-
- public FileUploadException() {
- this(null, null);
- }
-
- public FileUploadException(String message) {
- this(message, null);
- }
-
- public FileUploadException(String message, Throwable cause) {
- super(message, cause);
- }
-}
Modified:
trunk/ui/input/ui/src/main/java/org/richfaces/renderkit/FileUploadRendererBase.java
===================================================================
---
trunk/ui/input/ui/src/main/java/org/richfaces/renderkit/FileUploadRendererBase.java 2011-04-21
12:16:50 UTC (rev 22435)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/renderkit/FileUploadRendererBase.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -31,18 +31,22 @@
/**
* @author Konstantin Mishin
- *
+ * @author Nick Belaevski
*/
public class FileUploadRendererBase extends RendererBase {
@Override
protected void doDecode(FacesContext context, UIComponent component) {
ExternalContext externalContext = context.getExternalContext();
- Object request = externalContext.getRequest();
- if (request instanceof MultipartRequest) {
- UploadedFile file = ((MultipartRequest)
request).getUploadedFile(component.getClientId(context));
- if (file != null) {
- component.queueEvent(new FileUploadEvent(component, file));
+ MultipartRequest multipartRequest = (MultipartRequest)
externalContext.getRequestMap().get(MultipartRequest.REQUEST_ATTRIBUTE_NAME);
+ if (multipartRequest != null) {
+ String clientId = component.getClientId(context);
+
+ for (UploadedFile file : multipartRequest.getUploadedFiles()) {
+ if (clientId.equals(file.getParameterName())) {
+ component.queueEvent(new FileUploadEvent(component, file));
+ break;
+ }
}
}
}
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/BaseMultipartRequest.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/BaseMultipartRequest.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/request/BaseMultipartRequest.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Maps;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+abstract class BaseMultipartRequest extends HttpServletRequestWrapper implements
MultipartRequest {
+
+ static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
+
+ static final Map<String, String> HEADERS_MAP;
+
+ static {
+ HEADERS_MAP = Maps.newHashMap();
+
+ HEADERS_MAP.put("accept", "text/html");
+ HEADERS_MAP.put("faces-request", "partial/ajax");
+ HEADERS_MAP.put("content-type", CONTENT_TYPE);
+ }
+
+ private String uploadId;
+
+ private ProgressControl progressControl;
+
+ /**
+ * @param request
+ */
+ public BaseMultipartRequest(HttpServletRequest request, String uploadId,
ProgressControl progressControl) {
+ super(request);
+ this.uploadId = uploadId;
+ this.progressControl = progressControl;
+ }
+
+ public String getUploadId() {
+ return uploadId;
+ }
+
+ public void release() {
+ progressControl.clearProgress();
+ }
+
+ @Override
+ public String getHeader(String name) {
+ String headerValue = HEADERS_MAP.get(name.toLowerCase(Locale.US));
+
+ if (!Strings.isNullOrEmpty(headerValue)) {
+ return headerValue;
+ }
+
+ return super.getHeader(name);
+ }
+
+ @Override
+ public String getContentType() {
+ return getHeader("Content-Type");
+ }
+
+}
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/BaseUploadedFile.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/BaseUploadedFile.java
(rev 0)
+++ trunk/ui/input/ui/src/main/java/org/richfaces/request/BaseUploadedFile.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.richfaces.exception.FileUploadException;
+import org.richfaces.model.UploadedFile;
+
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Closeables;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public abstract class BaseUploadedFile implements UploadedFile {
+
+ private String parameterName;
+
+ public BaseUploadedFile(String parameterName) {
+ super();
+ this.parameterName = parameterName;
+ }
+
+ public String getParameterName() {
+ return parameterName;
+ }
+
+ public String getName() {
+ return getHeader(MultipartRequestParser.PARAM_FILENAME);
+ }
+
+ public String getContentType() {
+ return getHeader(MultipartRequestParser.PARAM_CONTENT_TYPE);
+ }
+
+ public byte[] getData() {
+ long size = getSize();
+
+ if (size > Integer.MAX_VALUE) {
+ throw new FileUploadException("Resource content is too long to be
allocated as byte[]");
+ }
+
+ InputStream is = null;
+ try {
+ is = getInputStream();
+ byte[] result = new byte[(int) size];
+ ByteStreams.readFully(is, result);
+ return result;
+ } catch (IOException e) {
+ throw new FileUploadException(e.getMessage(), e);
+ } finally {
+ Closeables.closeQuietly(is);
+ }
+ }
+
+}
Deleted: trunk/ui/input/ui/src/main/java/org/richfaces/request/FileParam.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/FileParam.java 2011-04-21
12:16:50 UTC (rev 22435)
+++ trunk/ui/input/ui/src/main/java/org/richfaces/request/FileParam.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -1,173 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright ${year}, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.richfaces.request;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.richfaces.exception.FileUploadException;
-import org.richfaces.log.Logger;
-import org.richfaces.log.RichfacesLogger;
-import org.richfaces.model.UploadedFile;
-
-/**
- * @author Konstantin Mishin
- *
- */
-class FileParam implements Param, UploadedFile {
-
- private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
-
- private String name;
- private String contentType;
- private OutputStream outputStream;
- private File file;
- private byte[] data;
-
- public FileParam(String name, String contentType, boolean createTempFiles, String
tempFilesDirectory) {
- if (createTempFiles) {
- try {
- File dir = null;
- if (tempFilesDirectory != null) {
- dir = new File(tempFilesDirectory);
- }
- file = File.createTempFile("richfaces_uploaded_file_", null,
dir);
- file.deleteOnExit();
- outputStream = new FileOutputStream(file);
- } catch (IOException ex) {
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException e) {
- LOGGER.error(e.getMessage(), e);
- }
- }
- throw new FileUploadException("Could not create temporary
file");
- }
- } else {
- outputStream = new ByteArrayOutputStream();
- }
- this.name = name;
- this.contentType = contentType;
- }
-
- public String getName() {
- return name;
- }
-
- public String getContentType() {
- return contentType;
- }
-
- public long getSize() {
- long size = -1;
- if (data != null) {
- size = data.length;
- } else {
- size = file.length();
- }
- return size;
- }
-
- public byte[] getData() {
- byte[] result = null;
- if (data != null) {
- result = data;
- } else {
- long fileLength = file.length();
- if (fileLength > Integer.MAX_VALUE) {
- throw new IllegalArgumentException("File content is too long to be
allocated as byte[]");
- } else {
- FileInputStream inputStream = null;
- try {
- inputStream = new FileInputStream(file);
- byte[] fileData = new byte[(int) fileLength];
- int totalRead = 0;
- int read;
- do {
- read = inputStream.read(fileData, totalRead, fileData.length -
totalRead);
- totalRead += read;
- } while (read > 0);
- result = fileData;
- } catch (IOException ex) {
- LOGGER.error(ex.getMessage(), ex);
- } finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- LOGGER.error(e.getMessage(), e);
- }
- }
- }
- }
- }
- return result;
- }
-
- public InputStream getInputStream() {
- InputStream stream = null;
- if (data != null) {
- stream = new ByteArrayInputStream(data);
- } else {
- try {
- stream = new FileInputStream(file);
- } catch (FileNotFoundException ex) {
- LOGGER.error(ex.getMessage(), ex);
- }
- }
- return stream;
- }
-
- public void complete() throws IOException {
- if (outputStream instanceof ByteArrayOutputStream) {
- data = ((ByteArrayOutputStream) outputStream).toByteArray();
- } else {
- try {
- outputStream.close();
- } catch (IOException ex) {
- LOGGER.error(ex.getMessage(), ex);
- }
- }
- outputStream = null;
- }
-
- public void clear() {
- if (data != null) {
- data = null;
- } else {
- file.delete();
- }
- }
-
- public void handle(byte[] bytes, int length) throws IOException {
- outputStream.write(bytes, 0, length);
- outputStream.flush();
- }
-}
\ No newline at end of file
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadDiscResource.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadDiscResource.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadDiscResource.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+
+import com.google.common.io.Closeables;
+
+/**
+ * @author Nick Belaevski
+ */
+final class FileUploadDiscResource extends FileUploadResource {
+
+ private File file;
+
+ private FileOutputStream fos;
+
+ public FileUploadDiscResource(String name, String uploadLocation) {
+ super(name, uploadLocation);
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream(file);
+ }
+
+ @Override
+ public long getSize() {
+ return file.length();
+ }
+
+ @Override
+ public void write(String fileName) throws IOException {
+ boolean writeResult = file.renameTo(getOutputFile(fileName));
+
+ if (!writeResult) {
+ throw new IOException(MessageFormat.format("Write to disc resource {0}
failed", fileName));
+ }
+ }
+
+ @Override
+ public void delete() throws IOException {
+ complete();
+
+ if (file == null || !file.exists()) {
+ return;
+ }
+
+ boolean deleteResult = file.delete();
+
+ if (!deleteResult) {
+ throw new IOException("File delete failed");
+ }
+ }
+
+ public void create() throws IOException {
+ file = File.createTempFile("richfaces_uploaded_file_", null,
getOutputFile(null));
+ file.deleteOnExit();
+ fos = new FileOutputStream(file);
+ }
+
+ public void handle(byte[] bytes, int length) throws IOException {
+ fos.write(bytes, 0, length);
+ }
+
+ public void complete() {
+ Closeables.closeQuietly(fos);
+ fos = null;
+ }
+
+}
Added:
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadMemoryResource.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadMemoryResource.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadMemoryResource.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,92 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.ajax4jsf.io.ByteBuffer;
+import org.ajax4jsf.io.FastBufferInputStream;
+
+import com.google.common.io.Files;
+import com.google.common.io.InputSupplier;
+
+/**
+ * @author Nick Belaevski
+ */
+class FileUploadMemoryResource extends FileUploadResource {
+
+ private ByteBuffer buffer;
+
+ public FileUploadMemoryResource(String name, String uploadLocation) {
+ super(name, uploadLocation);
+ }
+
+ private void checkNotDeleted() throws IOException {
+ if (buffer == null) {
+ throw new IOException("Resource has been deleted");
+ }
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ checkNotDeleted();
+
+ return new FastBufferInputStream(buffer);
+ }
+
+ @Override
+ public long getSize() {
+ return buffer.getLast().getTotalSize();
+ }
+
+ @Override
+ public void write(String fileName) throws IOException {
+ checkNotDeleted();
+
+ InputSupplier<InputStream> inputSupplier = new
InputSupplier<InputStream>() {
+ public InputStream getInput() throws IOException {
+ return getInputStream();
+ }
+ };
+
+ Files.copy(inputSupplier, getOutputFile(fileName));
+ }
+
+ @Override
+ public void delete() throws IOException {
+ buffer = null;
+ }
+
+ public void handle(byte[] bytes, int length) throws IOException {
+ buffer.append(bytes, 0, length);
+ }
+
+ public void create() {
+ buffer = new ByteBuffer(128);
+ }
+
+ public void complete() {
+ buffer.compact();
+ }
+
+}
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadParam.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadParam.java
(rev 0)
+++ trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadParam.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+
+import org.richfaces.request.ByteSequenceMatcher.BytesHandler;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+interface FileUploadParam extends BytesHandler {
+
+ public void create() throws IOException;
+
+ public void complete();
+
+ public String getName();
+
+ public boolean isFileParam();
+
+ public String getValue();
+
+ public FileUploadResource getResource();
+
+}
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadResource.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadResource.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadResource.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.google.common.base.Strings;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+abstract class FileUploadResource implements FileUploadParam {
+
+ private String name;
+
+ private String uploadLocation;
+
+ public FileUploadResource(String name, String uploadLocation) {
+ super();
+
+ this.name = name;
+ this.uploadLocation = uploadLocation;
+ }
+
+ protected String getUploadLocation() {
+ return uploadLocation;
+ }
+
+ protected File getOutputFile(String name) {
+ if (Strings.isNullOrEmpty(name)) {
+ return new File(uploadLocation);
+ }
+
+ return new File(uploadLocation, name);
+ }
+
+ public abstract InputStream getInputStream() throws IOException;
+
+ public abstract long getSize();
+
+ public abstract void write(String fileName) throws IOException;
+
+ public abstract void delete() throws IOException;
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isFileParam() {
+ return true;
+ }
+
+ public String getValue() {
+ return null;
+ }
+
+ public FileUploadResource getResource() {
+ return this;
+ }
+}
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadValueParam.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadValueParam.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/request/FileUploadValueParam.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,100 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import javax.faces.FacesException;
+
+import org.ajax4jsf.io.ByteBuffer;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+final class FileUploadValueParam implements FileUploadParam {
+
+ private ByteBuffer buffer;
+
+ private String name;
+
+ private String encoding;
+
+ private String value;
+
+ public FileUploadValueParam(String name, String encoding) {
+ super();
+
+ this.name = name;
+ this.encoding = encoding;
+ }
+
+ private byte[] getBufferBytes() {
+ byte[] bs = new byte[buffer.getLast().getTotalSize()];
+
+ int pos = 0;
+ ByteBuffer currentBuffer = buffer;
+ while (currentBuffer != null) {
+ System.arraycopy(currentBuffer.getBytes(), 0, bs, pos,
currentBuffer.getUsedSize());
+ pos += currentBuffer.getUsedSize();
+ currentBuffer = currentBuffer.getNext();
+ }
+
+ return bs;
+ }
+
+ public void handle(byte[] bytes, int length) throws IOException {
+ buffer.append(bytes, 0, length);
+ }
+
+ public void create() throws IOException {
+ buffer = new ByteBuffer(256);
+ }
+
+ public void complete() {
+ byte[] bytes = getBufferBytes();
+ buffer = null;
+
+ try {
+ value = (encoding != null) ? new String(bytes, encoding) : new
String(bytes);
+ } catch (UnsupportedEncodingException e) {
+ throw new FacesException(e.getMessage(), e);
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isFileParam() {
+ return false;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public FileUploadResource getResource() {
+ return null;
+ }
+}
Modified: trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequest.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequest.java 2011-04-21
12:16:50 UTC (rev 22435)
+++ trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequest.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -1,641 +1,46 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright ${year}, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.richfaces.request;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-
-import org.richfaces.exception.FileUploadException;
-import org.richfaces.log.Logger;
-import org.richfaces.log.RichfacesLogger;
-import org.richfaces.model.UploadedFile;
-import org.richfaces.request.ByteSequenceMatcher.BytesHandler;
-
-public class MultipartRequest extends HttpServletRequestWrapper {
-
- public static final String TEXT_HTML = "text/html";
-
- /** Session bean name where progress bar's percent map will be stored */
- public static final String PERCENT_BEAN_NAME =
"_richfaces_upload_percents";
-
- private static final BytesHandler NOOP_HANDLER = new BytesHandler() {
- public void handle(byte[] bytes, int length) {
- // do nothing
- }
- };
-
- /** Session bean name where request size will be stored */
- private static final String REQUEST_SIZE_BEAN_NAME =
"_richfaces_request_size";
-
- private static final String PARAM_NAME = "name";
- private static final String PARAM_FILENAME = "filename";
- private static final String PARAM_CONTENT_TYPE = "Content-Type";
-
- private static final int BUFFER_SIZE = 2048;
- private static final int CHUNK_SIZE = 1024;
- private static final int MAX_HEADER_SIZE = 32768;
-
- private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
-
- private static final byte CR = 0x0d;
- private static final byte LF = 0x0a;
- private static final byte[] CR_LF = {CR, LF};
- private static final byte[] HYPHENS = {0x2d, 0x2d}; // '--'
-
- private static final Pattern PARAM_VALUE_PATTERN =
Pattern.compile("^\\s*([^\\s=]+)\\s*[=:]\\s*(.+)\\s*$");
-
- private static final Pattern FILE_NAME_PATTERN =
Pattern.compile(".*filename=\"(.*)\"");
-
- private boolean createTempFiles;
-
- private String tempFilesDirectory;
-
- private String uid;
-
- private String encoding = null;
-
- private long contentLength = 0;
-
- private long bytesRead = 0;
-
- // we shouldn't allow to stop until request reaches PhaseListener because of
portlets
- private volatile boolean canStop = false;
-
- private Map<String, Param> parameters = null;
-
- private Map<String, Object> percentMap = null;
-
- private Map<String, Long> requestSizeMap = null;
-
- private List<String> keys = new ArrayList<String>();
-
- private byte[] boundaryMarker;
-
- private ByteSequenceMatcher sequenceMatcher;
-
- private boolean shouldStop = false;
- private boolean canceled;
-
- private boolean initialized = false;
-
- private HeadersHandler headersHandler = null;
-
- public MultipartRequest(HttpServletRequest request, boolean createTempFiles, String
tempFilesDirectory,
- String uid) {
- super(request);
- this.createTempFiles = createTempFiles;
- this.tempFilesDirectory = tempFilesDirectory;
- this.uid = uid;
- this.contentLength =
Long.parseLong(request.getHeader("Content-Length"));
- }
-
- private class ControlledProgressInputStream extends FilterInputStream {
-
- protected ControlledProgressInputStream(InputStream in) {
- super(in);
- }
-
- @Override
- public int read() throws IOException {
- int read = super.read();
- if (read >= 0) {
- bytesRead++;
- fillProgressInfo();
- }
- return read;
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- int read = super.read(b);
- if (read > 0) {
- bytesRead += read;
- fillProgressInfo();
- }
- return read;
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- int read = super.read(b, off, len);
- if (read > 0) {
- bytesRead += read;
- fillProgressInfo();
- }
- return read;
- }
- }
-
- private String decodeFileName(String name) {
- String fileName = null;
- try {
- StringBuffer buffer = new StringBuffer();
- String[] codes = name.split(";");
- if (codes != null) {
- for (String code : codes) {
- if (code.startsWith("&")) {
- String sCode = code.replaceAll("[&#]*",
"");
- Integer iCode = Integer.parseInt(sCode);
- buffer.append(Character.toChars(iCode));
- } else {
- buffer.append(code);
- }
- }
- fileName = buffer.toString();
- }
- } catch (Exception e) {
- fileName = name;
- }
-
- return fileName;
- }
-
- public void cancel() {
- this.canceled = true;
-
- if (parameters != null) {
- Iterator<Param> it = parameters.values().iterator();
- while (it.hasNext()) {
- Param p = it.next();
- if (p instanceof FileParam) {
- ((FileParam) p).clear();
- }
- }
- }
- }
-
- private void readNext() throws IOException {
- Param p = readHeader();
- if (p != null) {
- try {
- readData(p);
- } finally {
- try {
- p.complete();
- } catch (IOException e) {
- LOGGER.error(e.getMessage(), e);
- }
- }
- }
- }
-
- private Param createParam(Map<String, String> headers) {
- Param param = null;
- String paramName = headers.get(PARAM_NAME);
- if (paramName != null) {
- if (headers.containsKey(PARAM_FILENAME)) {
- param = new FileParam(decodeFileName(headers.get(PARAM_FILENAME)),
headers.get(PARAM_CONTENT_TYPE),
- createTempFiles, tempFilesDirectory);
- this.keys.add(paramName);
- } else {
- if (parameters.containsKey(paramName)) {
- param = parameters.get(paramName);
- } else {
- param = new ValueParam(encoding);
- }
- }
-
- if (!parameters.containsKey(paramName)) {
- parameters.put(paramName, param);
- }
- }
-
- return param;
- }
-
- private class HeadersHandler implements BytesHandler {
-
- private ByteArrayOutputStream baos = new ByteArrayOutputStream(BUFFER_SIZE);
-
- public void handle(byte[] bytes, int length) throws IOException {
- if (length != 0) {
- if (baos.size() + length > MAX_HEADER_SIZE) {
- throw new IOException("Header section is too big");
- }
-
- baos.write(bytes, 0, length);
- }
- }
-
- public boolean dataEquals(byte[] bytes) {
- return (baos.size() == bytes.length) && Arrays.equals(HYPHENS,
baos.toByteArray());
- }
-
- public String asString() throws UnsupportedEncodingException {
- if (encoding != null) {
- return baos.toString(encoding);
- } else {
- return baos.toString();
- }
- }
-
- public void reset() {
- baos.reset();
- }
-
- }
-
- private Param readHeader() throws IOException {
- if (sequenceMatcher.isEOF()) {
- return null;
- }
-
- if (headersHandler == null) {
- headersHandler = new HeadersHandler();
- } else {
- headersHandler.reset();
- }
-
- sequenceMatcher.setBytesHandler(headersHandler);
- sequenceMatcher.findSequence(-1, CR_LF);
-
- if (sequenceMatcher.isMatchedAndNotEOF() &&
!headersHandler.dataEquals(HYPHENS)) {
- headersHandler.reset();
-
- sequenceMatcher.findSequence(-1, CR_LF, CR_LF);
-
- if (!sequenceMatcher.isMatchedAndNotEOF()) {
- throw new IOException("Request header cannot be read");
- }
-
- String headersString = headersHandler.asString();
- Map<String, String> headers = new HashMap<String, String>();
- String[] split = headersString.split("\r\n");
- for (String headerString : split) {
- parseParams(headerString, "; ", headers);
- }
-
- return createParam(headers);
- }
-
- return null;
- }
-
- private void readProlog() throws IOException {
- sequenceMatcher.setBytesHandler(NOOP_HANDLER);
- sequenceMatcher.findSequence(-1, HYPHENS, boundaryMarker);
- if (!sequenceMatcher.isMatchedAndNotEOF()) {
- throw new IOException("Request prolog cannot be read");
- }
- }
-
- private void readData(final Param param) throws IOException {
- sequenceMatcher.setBytesHandler(param);
- sequenceMatcher.findSequence(CHUNK_SIZE, CR_LF, HYPHENS, boundaryMarker);
- if (!this.sequenceMatcher.isMatchedAndNotEOF()) {
- throw new IOException("Request data cannot be read");
- }
- }
-
- private void initialize() throws IOException {
- if (!initialized) {
- initialized = true;
-
- this.boundaryMarker = getBoundaryMarker(super.getContentType());
- if (this.boundaryMarker == null) {
- throw new FileUploadException("The request was rejected because
" + "no multipart boundary was found");
- }
-
- if (HYPHENS.length + boundaryMarker.length + CHUNK_SIZE + CR_LF.length >
BUFFER_SIZE) {
- throw new FileUploadException("Boundary marker is too long");
- }
-
- this.encoding = getCharacterEncoding();
-
- this.parameters = new HashMap<String, Param>();
-
- InputStream input = new ControlledProgressInputStream(getInputStream());
-
- this.sequenceMatcher = new ByteSequenceMatcher(input, BUFFER_SIZE);
-
- setupProgressData();
-
- readProlog();
- }
- }
-
- public void parseRequest() {
- canStop = true;
-
- setupProgressData();
-
- try {
- initialize();
-
- while (!sequenceMatcher.isEOF()) {
- readNext();
- }
- } catch (IOException e) {
- this.cancel();
-
- if (!this.shouldStop) {
- throw new FileUploadException("IO Error parsing multipart
request", e);
- }
- } finally {
- canStop = false;
- }
- }
-
- @SuppressWarnings("unchecked")
- private void setupProgressData() {
- if (percentMap == null || requestSizeMap == null) {
- FacesContext facesContext = FacesContext.getCurrentInstance();
- if (facesContext != null) {
- ExternalContext externalContext = facesContext.getExternalContext();
- if (externalContext != null) {
- Map<String, Object> sessionMap =
externalContext.getSessionMap();
- if (sessionMap != null) {
- String uploadId = getUploadId();
-
- synchronized (sessionMap) {
- if (percentMap == null) {
- percentMap = (Map<String, Object>)
sessionMap.get(PERCENT_BEAN_NAME);
- if (percentMap == null) {
- percentMap = new ConcurrentHashMap<String,
Object>();
- sessionMap.put(PERCENT_BEAN_NAME, percentMap);
- }
- }
-
- if (requestSizeMap == null) {
- requestSizeMap = (Map<String, Long>)
sessionMap.get(REQUEST_SIZE_BEAN_NAME);
- if (requestSizeMap == null) {
- requestSizeMap = new ConcurrentHashMap<String,
Long>();
- sessionMap.put(REQUEST_SIZE_BEAN_NAME,
requestSizeMap);
- }
- }
- }
-
- percentMap.put(uploadId, Double.valueOf(0));
-
- requestSizeMap.put(uploadId, contentLength);
- }
- }
- }
- }
- }
-
- private void fillProgressInfo() {
- setupProgressData();
-
- if (percentMap != null) {
- Double percent = (Double) (100.0 * this.bytesRead / this.contentLength);
- percentMap.put(uid, percent);
- // this.percent = percent;
- }
- }
-
- private byte[] getBoundaryMarker(String contentType) {
- Map<String, String> params = parseParams(contentType, ";");
- String boundaryStr = (String) params.get("boundary");
-
- if (boundaryStr == null) {
- return null;
- }
-
- try {
- return boundaryStr.getBytes("ISO-8859-1");
- } catch (UnsupportedEncodingException e) {
- return boundaryStr.getBytes();
- }
- }
-
- private Map<String, String> parseParams(String paramStr, String separator) {
- Map<String, String> paramMap = new HashMap<String, String>();
- parseParams(paramStr, separator, paramMap);
- return paramMap;
- }
-
- private void parseParams(String paramStr, String separator, Map<String, String>
paramMap) {
- String[] parts = paramStr.split(separator);
-
- for (String part : parts) {
- Matcher m = PARAM_VALUE_PATTERN.matcher(part);
- if (m.matches()) {
- String key = m.group(1);
- String value = m.group(2);
-
- // Strip double quotes
- if (value.startsWith("\"") &&
value.endsWith("\"")) {
- value = value.substring(1, value.length() - 1);
- }
- if (!"filename".equals(key)) {
- paramMap.put(key, value);
- } else {
- paramMap.put(key, parseFileName(paramStr));
- }
- }
- }
- }
-
- private String parseFileName(String parseStr) {
- Matcher m = FILE_NAME_PATTERN.matcher(parseStr);
- if (m.matches()) {
- String name = m.group(1);
- if (name.startsWith("&")) {
- return decodeFileName(name);
- } else {
- return name;
- }
- }
- return null;
- }
-
- private Param getParam(String name) {
- Param param = null;
- if (parameters != null) {
- param = parameters.get(name);
- }
-
- if (param == null) {
- if (!canceled) {
- try {
- initialize();
-
- while (param == null && !sequenceMatcher.isEOF()) {
- readNext();
- param = parameters.get(name);
- }
- } catch (IOException e) {
- this.cancel();
- throw new FileUploadException("IO Error parsing multipart
request", e);
- }
- }
- }
-
- return param;
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- public Enumeration getParameterNames() {
- if (parameters == null) {
- parseRequest();
- }
-
- return Collections.enumeration(parameters.keySet());
- }
-
- public byte[] getFileBytes(String name) {
- Param p = getParam(name);
- return (p != null && p instanceof FileParam) ? ((FileParam) p).getData()
: null;
- }
-
- @Override
- public String getParameter(String name) {
- Param p = getParam(name);
- if (p != null && p instanceof ValueParam) {
- ValueParam vp = (ValueParam) p;
- if (vp.getValue() instanceof String) {
- return (String) vp.getValue();
- }
- } else if (p != null && p instanceof FileParam) {
- return "---BINARY DATA---";
- } else {
- return super.getParameter(name);
- }
-
- return null;
- }
-
- @Override
- public String[] getParameterValues(String name) {
- parseRequest();
-
- Param p = getParam(name);
- if (p != null && p instanceof ValueParam) {
- ValueParam vp = (ValueParam) p;
- if (vp.getValue() instanceof List<?>) {
- @SuppressWarnings("unchecked")
- List<String> vals = (List<String>) vp.getValue();
- String[] values = new String[vals.size()];
- vals.toArray(values);
- return values;
- } else {
- return new String[] {(String) vp.getValue()};
- }
- } else {
- return super.getParameterValues(name);
- }
- }
-
- @Override
- public Map<String, Object> getParameterMap() {
- if (parameters == null) {
- parseRequest();
- }
-
- @SuppressWarnings("unchecked")
- Map<String, Object> params = new HashMap<String,
Object>(super.getParameterMap());
-
- for (String name : parameters.keySet()) {
- Param p = parameters.get(name);
- if (p instanceof ValueParam) {
- ValueParam vp = (ValueParam) p;
- if (vp.getValue() instanceof String) {
- params.put(name, vp.getValue());
- } else if (vp.getValue() instanceof List) {
- params.put(name, getParameterValues(name));
- }
- }
- }
-
- return params;
- }
-
- public UploadedFile getUploadedFile(String name) {
- Param param = getParam(name);
- if (param instanceof UploadedFile) {
- return (UploadedFile) param;
- } else {
- return null;
- }
- }
-
- public boolean isFormUpload() {
- return "_richfaces_form_upload".equals(uid);
- }
-
- @Override
- public String getHeader(String name) {
- if ("Accept".equals(name)) {
- return TEXT_HTML;
- } else if ("Faces-Request".equals(name)) {
- return "partial/ajax";
- } else {
- return super.getHeader(name);
- }
- }
-
- public void stop() {
- if (canStop) {
- shouldStop = true;
- }
- }
-
- public boolean isStopped() {
- return this.shouldStop;
- }
-
- public boolean isDone() {
- return !(this.contentLength != this.bytesRead && this.shouldStop
&& this.canceled);
- }
-
- @Override
- public String getContentType() {
- return "application/x-www-form-urlencoded";
- }
-
- public String getUploadId() {
- return uid;
- }
-
- public void clearRequestData() {
- String uploadId = getUploadId();
-
- if (percentMap != null) {
- percentMap.remove(uploadId);
- }
-
- if (requestSizeMap != null) {
- requestSizeMap.remove(uploadId);
- }
- }
-}
\ No newline at end of file
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import org.richfaces.model.UploadedFile;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface MultipartRequest {
+
+ public static final String REQUEST_ATTRIBUTE_NAME =
MultipartRequest.class.getName();
+
+ public enum ResponseState {
+ ok, sizeExceeded, serverError
+ }
+
+ public Iterable<UploadedFile> getUploadedFiles();
+
+ public ResponseState getResponseState();
+
+ public void release();
+
+ public String getUploadId();
+
+}
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequest25.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequest25.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequest25.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,153 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+import org.richfaces.model.UploadedFile;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+
+public class MultipartRequest25 extends BaseMultipartRequest {
+
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
+ private static final Function<Collection<String>, Object>
MULTIMAP_VALUE_TRANSFORMER = new Function<Collection<String>, Object>() {
+ public Object apply(Collection<String> input) {
+ if (input.isEmpty()) {
+ return null;
+ }
+
+ if (input.size() == 1) {
+ return Iterables.get(input, 0);
+ }
+
+ return input.toArray(new String[input.size()]);
+ }
+ };
+
+ private Multimap<String, String> params;
+
+ private Iterable<UploadedFile> uploadedFiles;
+
+ private ResponseState responseState;
+
+ public MultipartRequest25(HttpServletRequest request, String uploadId,
ProgressControl progressControl,
+ Multimap<String, String> params, Iterable<UploadedFile>
uploadedFiles, ResponseState responseState) {
+ super(request, uploadId, progressControl);
+
+ this.params = params;
+ this.uploadedFiles = uploadedFiles;
+ this.responseState = responseState;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Enumeration getParameterNames() {
+ Collection<Object> result = Sets.newHashSet();
+
+ Enumeration names = super.getParameterNames();
+ while (names.hasMoreElements()) {
+ String name = (String) names.nextElement();
+
+ result.add(name);
+ }
+
+ result.addAll(params.keySet());
+
+ return Iterators.asEnumeration(result.iterator());
+ }
+
+ @Override
+ public String getParameter(String name) {
+ String parameter = super.getParameter(name);
+ if (parameter != null) {
+ return parameter;
+ }
+
+ Collection<String> values = params.get(name);
+
+ if (values.isEmpty()) {
+ return null;
+ }
+
+ return Iterables.get(values, 0);
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ String[] parameterValues = super.getParameterValues(name);
+ if (parameterValues != null) {
+ return parameterValues;
+ }
+
+ Collection<String> values = params.get(name);
+
+ if (values.isEmpty()) {
+ return null;
+ }
+
+ return values.toArray(new String[values.size()]);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public Map getParameterMap() {
+ Map parameterMap = Maps.newHashMap(super.getParameterMap());
+ parameterMap.putAll(Maps.transformValues(params.asMap(),
MULTIMAP_VALUE_TRANSFORMER));
+
+ return parameterMap;
+ }
+
+ public Iterable<UploadedFile> getUploadedFiles() {
+ return uploadedFiles;
+ }
+
+ public void release() {
+ super.release();
+
+ for (UploadedFile uploadedFile : uploadedFiles) {
+ try {
+ uploadedFile.delete();
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ public ResponseState getResponseState() {
+ return responseState;
+ }
+
+}
\ No newline at end of file
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequestParser.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequestParser.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/request/MultipartRequestParser.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,394 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.richfaces.exception.FileUploadException;
+import org.richfaces.log.Logger;
+import org.richfaces.log.RichfacesLogger;
+import org.richfaces.model.UploadedFile;
+import org.richfaces.request.ByteSequenceMatcher.BytesHandler;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public final class MultipartRequestParser {
+
+ static final String PARAM_NAME = "name";
+
+ static final String PARAM_FILENAME = "filename";
+
+ static final String PARAM_CONTENT_TYPE = "Content-Type";
+
+ private static final byte CR = 0x0d;
+
+ private static final byte LF = 0x0a;
+
+ private static final byte[] CR_LF = {CR, LF};
+
+ private static final byte[] HYPHENS = {0x2d, 0x2d}; // '--'
+
+ private static final int BUFFER_SIZE = 2048;
+
+ private static final int CHUNK_SIZE = 1024;
+
+ private static final int MAX_HEADER_SIZE = 32768;
+
+ private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
+
+ private static final Pattern FILE_NAME_PATTERN =
Pattern.compile(".*filename=\"(.*)\"");
+
+ private static final Pattern PARAM_VALUE_PATTERN =
Pattern.compile("^\\s*([^\\s=]+)\\s*[=:]\\s*(.+)\\s*$");
+
+ private static final BytesHandler NOOP_HANDLER = new BytesHandler() {
+ public void handle(byte[] bytes, int length) {
+ // do nothing
+ }
+ };
+
+ private class HeadersHandler implements BytesHandler {
+
+ private ByteArrayOutputStream baos = new ByteArrayOutputStream(BUFFER_SIZE);
+
+ public void handle(byte[] bytes, int length) throws IOException {
+ if (length != 0) {
+ if (baos.size() + length > MAX_HEADER_SIZE) {
+ throw new IOException("Header section is too big");
+ }
+
+ baos.write(bytes, 0, length);
+ }
+ }
+
+ public boolean dataEquals(byte[] bytes) {
+ return (baos.size() == bytes.length) && Arrays.equals(HYPHENS,
baos.toByteArray());
+ }
+
+ public String asString() throws UnsupportedEncodingException {
+ if (request.getCharacterEncoding() != null) {
+ return baos.toString(request.getCharacterEncoding());
+ } else {
+ return baos.toString();
+ }
+ }
+
+ public void reset() {
+ baos.reset();
+ }
+
+ }
+
+ private HttpServletRequest request;
+
+ private boolean createTempFiles;
+
+ private String tempFilesDirectory;
+
+ private Multimap<String, String> parametersMap = LinkedListMultimap.create();
+
+ private List<UploadedFile> uploadedFiles = Lists.newArrayList();
+
+ private byte[] boundaryMarker;
+
+ private ByteSequenceMatcher sequenceMatcher;
+
+ private HeadersHandler headersHandler;
+
+ private ProgressControl progressControl;
+
+ /**
+ * @param request
+ * @param createTempFiles
+ * @param tempFilesDirectory
+ * @param uploadId
+ */
+ public MultipartRequestParser(HttpServletRequest request, boolean createTempFiles,
String tempFilesDirectory,
+ ProgressControl progressControl) {
+
+ this.request = request;
+ this.createTempFiles = createTempFiles;
+ this.tempFilesDirectory = tempFilesDirectory;
+ this.progressControl = progressControl;
+ }
+
+ private void cancel() {
+ for (UploadedFile uploadedFile : uploadedFiles) {
+ try {
+ uploadedFile.delete();
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ public Multimap<String, String> getParameters() {
+ return parametersMap;
+ }
+
+ public Iterable<UploadedFile> getUploadedFiles() {
+ return uploadedFiles;
+ }
+
+ public void parse() throws FileUploadException {
+ try {
+ initialize();
+
+ while (!sequenceMatcher.isEOF()) {
+ readNext();
+ }
+ } catch (IOException e) {
+ this.cancel();
+
+ throw new FileUploadException(MessageFormat.format("Exception parsing
multipart request: {0}", e.getMessage()), e);
+ }
+ }
+
+ private void initialize() throws IOException, FileUploadException {
+ this.boundaryMarker = getBoundaryMarker(request.getContentType());
+ if (this.boundaryMarker == null) {
+ throw new FileUploadException("The request was rejected because no
multipart boundary was found");
+ }
+
+ if (HYPHENS.length + boundaryMarker.length + CHUNK_SIZE + CR_LF.length >
BUFFER_SIZE) {
+ throw new FileUploadException("Boundary marker is too long");
+ }
+
+ this.sequenceMatcher = new
ByteSequenceMatcher(progressControl.wrapStream(request.getInputStream()), BUFFER_SIZE);
+
+ readProlog();
+ }
+
+ private String getFirstParameterValue(Multimap<String, String> multimap, String
key) {
+ Collection<String> values = multimap.get(key);
+
+ if (values.isEmpty()) {
+ return null;
+ }
+
+ return Iterables.get(values, 0);
+ }
+
+ private byte[] getBoundaryMarker(String contentType) {
+ Multimap<String, String> params = parseParams(contentType, ";");
+ String boundaryStr = getFirstParameterValue(params, "boundary");
+
+ if (boundaryStr == null) {
+ return null;
+ }
+
+ try {
+ return boundaryStr.getBytes("ISO-8859-1");
+ } catch (UnsupportedEncodingException e) {
+ return boundaryStr.getBytes();
+ }
+ }
+
+ private Multimap<String, String> parseParams(String paramStr, String separator)
{
+ Multimap<String, String> paramMap = LinkedListMultimap.create();
+ parseParams(paramStr, separator, paramMap);
+ return paramMap;
+ }
+
+ private void parseParams(String paramStr, String separator, Multimap<String,
String> paramMap) {
+ String[] parts = paramStr.split(separator);
+
+ for (String part : parts) {
+ Matcher m = PARAM_VALUE_PATTERN.matcher(part);
+ if (m.matches()) {
+ String key = m.group(1).toLowerCase(Locale.US);
+ String value = m.group(2);
+
+ // Strip double quotes
+ if (value.startsWith("\"") &&
value.endsWith("\"")) {
+ value = value.substring(1, value.length() - 1);
+ }
+ if (!"filename".equals(key)) {
+ paramMap.put(key, value);
+ } else {
+ paramMap.put(key, parseFileName(paramStr));
+ }
+ }
+ }
+ }
+
+ //TODO - URI decoder?
+ private String decodeFileName(String name) {
+ String fileName = null;
+ try {
+ StringBuilder builder = new StringBuilder();
+ String[] codes = name.split(";");
+ if (codes != null) {
+ for (String code : codes) {
+ if (code.startsWith("&")) {
+ String sCode = code.replaceAll("[&#]*",
"");
+ Integer iCode = Integer.parseInt(sCode);
+ builder.append(Character.toChars(iCode));
+ } else {
+ builder.append(code);
+ }
+ }
+ fileName = builder.toString();
+ }
+ } catch (Exception e) {
+ fileName = name;
+ }
+
+ return fileName;
+ }
+
+ private String parseFileName(String parseStr) {
+ Matcher m = FILE_NAME_PATTERN.matcher(parseStr);
+ if (m.matches()) {
+ String name = m.group(1);
+ if (name.startsWith("&")) {
+ return decodeFileName(name);
+ } else {
+ return name;
+ }
+ }
+ return null;
+ }
+
+ private void readProlog() throws IOException {
+ sequenceMatcher.setBytesHandler(NOOP_HANDLER);
+ sequenceMatcher.findSequence(-1, HYPHENS, boundaryMarker);
+ if (!sequenceMatcher.isMatchedAndNotEOF()) {
+ throw new IOException("Request prolog cannot be read");
+ }
+ }
+
+ private void readData(FileUploadParam uploadParam) throws IOException {
+ sequenceMatcher.setBytesHandler(uploadParam);
+ sequenceMatcher.findSequence(CHUNK_SIZE, CR_LF, HYPHENS, boundaryMarker);
+ sequenceMatcher.setBytesHandler(null);
+ if (!this.sequenceMatcher.isMatchedAndNotEOF()) {
+ throw new IOException("Request data cannot be read");
+ }
+ }
+
+ private void readNext() throws IOException {
+ Multimap<String, String> headers = readHeaders();
+ FileUploadParam param = createParam(headers);
+
+ if (param == null) {
+ return;
+ }
+
+ param.create();
+
+ try {
+ readData(param);
+ } finally {
+ param.complete();
+ }
+
+ if (param.isFileParam()) {
+ uploadedFiles.add(new UploadedFile25(param.getName(), param.getResource(),
headers));
+ } else {
+ parametersMap.put(param.getName(), param.getValue());
+ }
+ }
+
+ private FileUploadParam createParam(Multimap<String, String> headers) {
+ if (headers == null) {
+ return null;
+ }
+
+ String parameterName = getFirstParameterValue(headers, PARAM_NAME);
+
+ if (Strings.isNullOrEmpty(parameterName)) {
+ return null;
+ }
+
+ boolean isFile = !Strings.isNullOrEmpty(getFirstParameterValue(headers,
PARAM_FILENAME));
+
+ FileUploadParam param;
+
+ if (isFile) {
+ if (createTempFiles) {
+ param = new FileUploadDiscResource(parameterName, tempFilesDirectory);
+ } else {
+ param = new FileUploadMemoryResource(parameterName, tempFilesDirectory);
+ }
+ } else {
+ param = new FileUploadValueParam(parameterName,
request.getCharacterEncoding());
+ }
+
+ return param;
+ }
+
+ private Multimap<String, String> readHeaders() throws IOException {
+ if (sequenceMatcher.isEOF()) {
+ return null;
+ }
+
+ if (headersHandler == null) {
+ headersHandler = new HeadersHandler();
+ } else {
+ headersHandler.reset();
+ }
+
+ sequenceMatcher.setBytesHandler(headersHandler);
+ sequenceMatcher.findSequence(-1, CR_LF);
+
+ if (sequenceMatcher.isMatchedAndNotEOF() &&
!headersHandler.dataEquals(HYPHENS)) {
+ headersHandler.reset();
+
+ sequenceMatcher.findSequence(-1, CR_LF, CR_LF);
+
+ if (!sequenceMatcher.isMatchedAndNotEOF()) {
+ throw new IOException("Request header cannot be read");
+ }
+
+ String headersString = headersHandler.asString();
+ Multimap<String, String> headers = LinkedListMultimap.create();
+ String[] split = headersString.split("\r\n");
+ for (String headerString : split) {
+ parseParams(headerString, "; ", headers);
+ }
+
+ return headers;
+ }
+
+ return null;
+ }
+
+}
Deleted: trunk/ui/input/ui/src/main/java/org/richfaces/request/Param.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/Param.java 2011-04-21 12:16:50
UTC (rev 22435)
+++ trunk/ui/input/ui/src/main/java/org/richfaces/request/Param.java 2011-04-21 12:19:14
UTC (rev 22436)
@@ -1,34 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright ${year}, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.richfaces.request;
-
-import java.io.IOException;
-
-import org.richfaces.request.ByteSequenceMatcher.BytesHandler;
-
-/**
- * @author Konstantin Mishin
- *
- */
-interface Param extends BytesHandler {
- void complete() throws IOException;
-}
\ No newline at end of file
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/ProgressControl.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/ProgressControl.java
(rev 0)
+++ trunk/ui/input/ui/src/main/java/org/richfaces/request/ProgressControl.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.util.Map;
+
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletInputStream;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public final class ProgressControl {
+
+ private static final String UPLOAD_PROGRESS_PREFIX =
"_richfaces_upload_percents";
+
+ private Map<String, Object> contextMap;
+
+ private String attributeName;
+
+ private long totalBytesRead = 0;
+
+ private long length;
+
+ private byte lastUpdatedPercentValue;
+
+ public ProgressControl(Map<String, Object> contextMap, String uploadId, long
length) {
+ this.contextMap = contextMap;
+ this.attributeName = getContextAttributeName(uploadId);
+ this.length = length;
+ }
+
+ public static byte getProgress(FacesContext context, String uploadId) {
+ Byte progress = (Byte)
context.getExternalContext().getSessionMap().get(getContextAttributeName(uploadId));
+
+ if (progress != null) {
+ return progress.byteValue();
+ }
+
+ return 0;
+ }
+
+ private static String getContextAttributeName(String uploadId) {
+ return UPLOAD_PROGRESS_PREFIX + uploadId;
+ }
+
+ void clearProgress() {
+ contextMap.remove(attributeName);
+ }
+
+ public void advance(long bytesRead) {
+ totalBytesRead += bytesRead;
+
+ byte percent;
+ if (length != 0) {
+ percent = (byte) Math.floor( ((double)totalBytesRead) / length * 100);
+ } else {
+ percent = 100;
+ }
+
+ if (percent > lastUpdatedPercentValue) {
+ lastUpdatedPercentValue = percent;
+ contextMap.put(attributeName, lastUpdatedPercentValue);
+ }
+ }
+
+ public ServletInputStream wrapStream(ServletInputStream inputStream) {
+ return new ProgressServletInputStream(inputStream, this);
+ }
+}
Added:
trunk/ui/input/ui/src/main/java/org/richfaces/request/ProgressServletInputStream.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/ProgressServletInputStream.java
(rev 0)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/request/ProgressServletInputStream.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+
+import javax.servlet.ServletInputStream;
+
+
+class ProgressServletInputStream extends ServletInputStream {
+
+ private ServletInputStream wrappedStream;
+
+ private ProgressControl progressControl;
+
+ protected ProgressServletInputStream(ServletInputStream wrappedStream,
ProgressControl progressControl) {
+ this.wrappedStream = wrappedStream;
+ this.progressControl = progressControl;
+ }
+
+ @Override
+ public int read() throws IOException {
+ int read = wrappedStream.read();
+ if (read >= 0) {
+ progressControl.advance(1);
+ }
+ return read;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ int read = wrappedStream.read(b);
+ if (read > 0) {
+ progressControl.advance(read);
+ }
+ return read;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ int read = wrappedStream.read(b, off, len);
+ if (read > 0) {
+ progressControl.advance(read);
+ }
+ return read;
+ }
+
+ @Override
+ public int readLine(byte[] b, int off, int len) throws IOException {
+ int read = wrappedStream.readLine(b, off, len);
+ if (read > 0) {
+ progressControl.advance(read);
+ }
+ return read;
+ }
+
+}
\ No newline at end of file
Added: trunk/ui/input/ui/src/main/java/org/richfaces/request/UploadedFile25.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/UploadedFile25.java
(rev 0)
+++ trunk/ui/input/ui/src/main/java/org/richfaces/request/UploadedFile25.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.request;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Locale;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class UploadedFile25 extends BaseUploadedFile {
+
+ private FileUploadResource uploadResource;
+
+ private Multimap<String, String> headersMap;
+
+ public UploadedFile25(String parameterName, FileUploadResource uploadResource,
+ Multimap<String, String> headersMap) {
+ super(parameterName);
+
+ this.uploadResource = uploadResource;
+ this.headersMap = headersMap;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return uploadResource.getInputStream();
+ }
+
+ public void delete() throws IOException {
+ uploadResource.delete();
+ }
+
+ public void write(String fileName) throws IOException {
+ uploadResource.write(fileName);
+ }
+
+ public String getHeader(String headerName) {
+ String lcHeaderName = headerName.toLowerCase(Locale.US);
+ Collection<String> headers = headersMap.get(lcHeaderName);
+
+ if (headers.isEmpty()) {
+ return null;
+ }
+
+ return Iterables.get(headers, 0);
+ }
+
+ public Collection<String> getHeaderNames() {
+ return new HashSet<String>(headersMap.keySet());
+ }
+
+ public Collection<String> getHeaders(String headerName) {
+ String lcHeaderName = headerName.toLowerCase(Locale.US);
+ Collection<String> headers = headersMap.get(lcHeaderName);
+
+ return new ArrayList<String>(headers);
+ }
+
+ public long getSize() {
+ return uploadResource.getSize();
+ }
+
+}
Deleted: trunk/ui/input/ui/src/main/java/org/richfaces/request/ValueParam.java
===================================================================
--- trunk/ui/input/ui/src/main/java/org/richfaces/request/ValueParam.java 2011-04-21
12:16:50 UTC (rev 22435)
+++ trunk/ui/input/ui/src/main/java/org/richfaces/request/ValueParam.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -1,64 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright ${year}, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.richfaces.request;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-class ValueParam implements Param {
-
- private Object value = null;
- private ByteArrayOutputStream buf = new ByteArrayOutputStream();
- private String encoding;
-
- public ValueParam(String encoding) {
- this.encoding = encoding;
- }
-
- @SuppressWarnings("unchecked")
- public void complete() throws IOException {
- String val = this.encoding == null ? new String(buf.toByteArray()) : new
String(buf.toByteArray(),
- this.encoding);
- if (value == null) {
- value = val;
- } else {
- if (!(value instanceof List<?>)) {
- List<String> v = new ArrayList<String>();
- v.add((String) value);
- value = v;
- }
-
- ((List<String>) value).add(val);
- }
- buf.reset();
- }
-
- public Object getValue() {
- return value;
- }
-
- public void handle(byte[] bytes, int length) throws IOException {
- buf.write(bytes, 0, length);
- }
-}
\ No newline at end of file
Modified:
trunk/ui/input/ui/src/main/java/org/richfaces/resource/FileUploadProgressResource.java
===================================================================
---
trunk/ui/input/ui/src/main/java/org/richfaces/resource/FileUploadProgressResource.java 2011-04-21
12:16:50 UTC (rev 22435)
+++
trunk/ui/input/ui/src/main/java/org/richfaces/resource/FileUploadProgressResource.java 2011-04-21
12:19:14 UTC (rev 22436)
@@ -21,12 +21,9 @@
*/
package org.richfaces.resource;
-import java.util.Map;
-
import javax.faces.context.FacesContext;
-import org.richfaces.context.FileUploadPartialViewContextFactory;
-import org.richfaces.request.MultipartRequest;
+import org.richfaces.request.ProgressControl;
/**
* @author Nick Belaevski
@@ -34,19 +31,12 @@
*/
public class FileUploadProgressResource extends AbstractJSONResource {
+ private static final Object UID_ALT_KEY = "rf_fu_uid_alt";
+
@Override
protected Object getData(FacesContext context) {
- Map<String, Object> sessionMap =
context.getExternalContext().getSessionMap();
- Map<String, Number> percentMap = (Map<String, Number>)
sessionMap.get(MultipartRequest.PERCENT_BEAN_NAME);
-
- Number result = null;
-
- if (percentMap != null) {
- String uploadId =
context.getExternalContext().getRequestParameterMap().get(FileUploadPartialViewContextFactory.UID_ALT_KEY);
- result = (Number) percentMap.get(uploadId);
- }
-
- return result != null ? result : 0;
+ String uploadId =
context.getExternalContext().getRequestParameterMap().get(UID_ALT_KEY);
+ return ProgressControl.getProgress(context, uploadId);
}
}
Modified: trunk/ui/input/ui/src/main/resources/META-INF/fileupload.faces-config.xml
===================================================================
--- trunk/ui/input/ui/src/main/resources/META-INF/fileupload.faces-config.xml 2011-04-21
12:16:50 UTC (rev 22435)
+++ trunk/ui/input/ui/src/main/resources/META-INF/fileupload.faces-config.xml 2011-04-21
12:19:14 UTC (rev 22436)
@@ -28,6 +28,7 @@
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:cdk="http://jboss.org/schema/richfaces/cdk/extensions"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<factory>
- <partial-view-context-factory>org.richfaces.context.FileUploadPartialViewContextFactory</partial-view-context-factory>
+
<faces-context-factory>org.richfaces.context.FileUploadFacesContextFactory</faces-context-factory>
+
<external-context-factory>org.richfaces.context.FileUploadExternalContextFactory</external-context-factory>
</factory>
</faces-config>
Modified:
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/fileupload.js
===================================================================
---
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/fileupload.js 2011-04-21
12:16:50 UTC (rev 22435)
+++
trunk/ui/input/ui/src/main/resources/META-INF/resources/org.richfaces/fileupload.js 2011-04-21
12:19:14 UTC (rev 22436)
@@ -191,7 +191,15 @@
responseStatus = id.split(":")[1];
}
if (responseStatus) {
- responseStatus == ITEM_STATE.DONE && jsf.ajax.response({responseXML:
contentDocument}, {});
+ var responseContext = {
+ source: this.element[0],
+ /* hack for MyFaces */
+ _mfInternal: {
+ _mfSourceControlId: this.element.attr('id')
+ }
+ };
+
+ responseStatus == ITEM_STATE.DONE && jsf.ajax.response({responseXML:
contentDocument}, responseContext);
this.loadableItem.finishUploading(responseStatus);
this.submitedItems.push(this.loadableItem);
if (responseStatus == ITEM_STATE.DONE && this.items.length) {