You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by jo...@apache.org on 2008/03/18 05:42:13 UTC
svn commit: r638212 - in /cocoon/branches/BRANCH_2_1_X:
src/java/org/apache/cocoon/servlet/multipart/MultipartParser.java
src/java/org/apache/cocoon/servlet/multipart/Part.java
src/java/org/apache/cocoon/servlet/multipart/PartInMemory.java status.xml
Author: joerg
Date: Mon Mar 17 21:42:08 2008
New Revision: 638212
URL: http://svn.apache.org/viewvc?rev=638212&view=rev
Log:
Close streams properly after copying Parts (MultipartParser). Allow to access InputStream of PartInMemory multiple times.
Modified:
cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/MultipartParser.java
cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/Part.java
cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/PartInMemory.java
cocoon/branches/BRANCH_2_1_X/status.xml
Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/MultipartParser.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/MultipartParser.java?rev=638212&r1=638211&r2=638212&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/MultipartParser.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/MultipartParser.java Mon Mar 17 21:42:08 2008
@@ -5,9 +5,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,7 +17,6 @@
package org.apache.cocoon.servlet.multipart;
import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -53,7 +52,7 @@
private final static int FILE_BUFFER_SIZE = 4096;
private static final int MAX_BOUNDARY_SIZE = 128;
-
+
private boolean saveUploadedFilesToDisk;
private File uploadDirectory = null;
@@ -61,23 +60,23 @@
private boolean allowOverwrite;
private boolean silentlyRename;
-
+
private int maxUploadSize;
private String characterEncoding;
-
+
private Hashtable parts;
-
+
private boolean oversized = false;
-
+
private int contentLength;
-
+
private HttpSession session;
-
+
private boolean hasSession;
-
+
private Hashtable uploadStatus;
-
+
/**
* Constructor, parses given request
*
@@ -116,19 +115,18 @@
TokenStream stream = new TokenStream(pushbackStream);
parseMultiPart(stream, getBoundary(contentType));
-
}
-
+
public Hashtable getParts(int contentLength, String contentType, InputStream requestStream)
throws IOException, MultipartException {
this.parts = new Hashtable();
parseParts(contentLength, contentType, requestStream);
return this.parts;
}
-
+
public Hashtable getParts(HttpServletRequest request) throws IOException, MultipartException {
this.parts = new Hashtable();
-
+
// Copy all parameters coming from the request URI to the parts table.
// This happens when a form's action attribute has some parameters
Enumeration names = request.getParameterNames();
@@ -151,21 +149,21 @@
this.uploadStatus.put("finished", Boolean.FALSE);
this.uploadStatus.put("sent", new Integer(0));
this.uploadStatus.put("total", new Integer(request.getContentLength()));
- this.uploadStatus.put("filename", "");
+ this.uploadStatus.put("filename", "");
this.uploadStatus.put("error", Boolean.FALSE);
this.uploadStatus.put("uploadsdone", new Integer(0));
this.session.setAttribute(UPLOAD_STATUS_SESSION_ATTR, this.uploadStatus);
}
- parseParts(request.getContentLength(), request.getContentType(), request.getInputStream());
+ parseParts(request.getContentLength(), request.getContentType(), request.getInputStream());
if (this.hasSession) {
this.uploadStatus.put("finished", Boolean.TRUE);
}
- return this.parts;
+ return this.parts;
}
-
+
/**
* Parse a multipart block
*
@@ -214,7 +212,7 @@
// empty upload fields. Just parse away the part
byte[] buf = new byte[32];
while(ts.getState() == TokenStream.STATE_READING)
- ts.read(buf);
+ ts.read(buf);
}
} else if (((String) headers.get("content-disposition"))
.toLowerCase().equals("form-data")) {
@@ -283,30 +281,31 @@
out = new FileOutputStream(file);
}
-
+
if (hasSession) { // upload widget support
this.uploadStatus.put("finished", Boolean.FALSE);
this.uploadStatus.put("started", Boolean.TRUE);
this.uploadStatus.put("widget", headers.get("name"));
this.uploadStatus.put("filename", headers.get("filename"));
}
-
+
int length = 0; // Track length for OversizedPart
try {
int read = 0;
- while (in.getState() == TokenStream.STATE_READING) { // read data
+ while (in.getState() == TokenStream.STATE_READING) {
+ // read data
read = in.read(buf);
length += read;
out.write(buf, 0, read);
-
+
if (this.hasSession) {
- this.uploadStatus.put("sent",
+ this.uploadStatus.put("sent",
new Integer(((Integer)this.uploadStatus.get("sent")).intValue() + read)
);
}
}
if (this.hasSession) { // upload widget support
- this.uploadStatus.put("uploadsdone",
+ this.uploadStatus.put("uploadsdone",
new Integer(((Integer)this.uploadStatus.get("uploadsdone")).intValue() + 1)
);
this.uploadStatus.put("error", Boolean.FALSE);
@@ -324,13 +323,13 @@
} finally {
if ( out!=null ) out.close();
}
-
+
String name = (String)headers.get("name");
if (oversized) {
this.parts.put(name, new RejectedPart(headers, length, this.contentLength, this.maxUploadSize));
} else if (file == null) {
byte[] bytes = ((ByteArrayOutputStream) out).toByteArray();
- this.parts.put(name, new PartInMemory(headers, new ByteArrayInputStream(bytes), bytes.length));
+ this.parts.put(name, new PartInMemory(headers, bytes));
} else {
this.parts.put(name, new PartOnDisk(headers, file));
}
@@ -347,14 +346,14 @@
private void parseInlinePart(TokenStream in, Hashtable headers)
throws IOException {
- // Buffer incoming bytes for proper string decoding (there can be multibyte chars)
+ // Buffer incoming bytes for proper string decoding (there can be multibyte chars)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while (in.getState() == TokenStream.STATE_READING) {
- int c = in.read();
- if (c != -1) bos.write(c);
+ int c = in.read();
+ if (c != -1) bos.write(c);
}
-
+
String field = (String) headers.get("name");
Vector v = (Vector) this.parts.get(field);
@@ -384,9 +383,9 @@
headers.put(tokenizer.nextToken(" :").toLowerCase(),
tokenizer.nextToken(" :;"));
- // The extra tokenizer.hasMoreTokens() in headers.put
- // handles the filename="" case IE6 submits for an empty
- // upload field.
+ // The extra tokenizer.hasMoreTokens() in headers.put
+ // handles the filename="" case IE6 submits for an empty
+ // upload field.
while (tokenizer.hasMoreTokens()) {
headers.put(tokenizer.nextToken(" ;=\""),
tokenizer.hasMoreTokens()?tokenizer.nextToken("=\""):"");
@@ -400,17 +399,14 @@
/**
* Get boundary from contentheader
- *
- * @param hdr
*/
private String getBoundary(String hdr) {
int start = hdr.toLowerCase().indexOf("boundary=");
if (start > -1) {
return "--" + hdr.substring(start + 9);
- } else {
- return null;
}
+ return null;
}
/**
@@ -421,9 +417,9 @@
* @throws IOException
*/
private String readln(TokenStream in) throws IOException {
-
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
-
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
int b = in.read();
while ((b != -1) && (b != '\r')) {
@@ -437,4 +433,5 @@
return new String(bos.toByteArray(), this.characterEncoding);
}
+
}
Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/Part.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/Part.java?rev=638212&r1=638211&r2=638212&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/Part.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/Part.java Mon Mar 17 21:42:08 2008
@@ -125,10 +125,16 @@
*/
public void copyToSource(ModifiableSource source) throws IOException {
InputStream is = getInputStream();
- OutputStream os = source.getOutputStream();
- IOUtils.copy(is, os);
- is.close();
- os.close();
+ try {
+ OutputStream os = source.getOutputStream();
+ try {
+ IOUtils.copy(is, os);
+ } finally {
+ os.close();
+ }
+ } finally {
+ is.close();
+ }
}
/**
@@ -140,10 +146,16 @@
*/
public void copyToFile(String filename) throws IOException {
InputStream is = getInputStream();
- OutputStream os = new FileOutputStream(filename);
- IOUtils.copy(is, os);
- is.close();
- os.close();
+ try {
+ OutputStream os = new FileOutputStream(filename);
+ try {
+ IOUtils.copy(is, os);
+ } finally {
+ os.close();
+ }
+ } finally {
+ is.close();
+ }
}
/**
Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/PartInMemory.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/PartInMemory.java?rev=638212&r1=638211&r2=638212&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/PartInMemory.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/servlet/multipart/PartInMemory.java Mon Mar 17 21:42:08 2008
@@ -16,6 +16,7 @@
*/
package org.apache.cocoon.servlet.multipart;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
@@ -28,21 +29,16 @@
*/
public class PartInMemory extends Part {
- private InputStream in;
-
+ private byte[] bytes;
private int size;
/**
* Constructor PartInMemory
- *
- * @param headers
- * @param in
- * @param size
*/
- public PartInMemory(Map headers, InputStream in, int size) {
+ public PartInMemory(Map headers, byte[] bytes) {
super(headers);
- this.in = in;
- this.size = size;
+ this.bytes = bytes;
+ this.size = bytes.length;
}
/**
@@ -65,17 +61,18 @@
* @throws IOException
*/
public InputStream getInputStream() throws IOException {
- if (this.in != null) {
- return this.in;
+ if (this.bytes != null) {
+ return new ByteArrayInputStream(this.bytes);
} else {
throw new IllegalStateException("This part has already been disposed.");
}
}
-
+
/**
* Clean the byte array content buffer holding part data
*/
public void dispose() {
- this.in = null;
+ this.bytes = null;
}
+
}
Modified: cocoon/branches/BRANCH_2_1_X/status.xml
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/status.xml?rev=638212&r1=638211&r2=638212&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/status.xml (original)
+++ cocoon/branches/BRANCH_2_1_X/status.xml Mon Mar 17 21:42:08 2008
@@ -182,6 +182,10 @@
<changes>
<release version="2.1.12" date="TBD">
+ <action dev="JH" type="fix">
+ Core: Close streams properly after copying Parts (MultipartParser). Allow to access InputStream of PartInMemory
+ multiple times.
+ </action>
<action dev="CZ" type="fix">
Portal: Remove user management tools.
</action>