jsdever 2002/10/28 22:40:15
Modified: httpclient/src/java/org/apache/commons/httpclient/methods/multipart
FilePart.java
httpclient/src/test/org/apache/commons/httpclient
TestNoHost.java
Added: httpclient/src/test/org/apache/commons/httpclient
TestPartsNoHost.java
Log:
Fix for file part failing to send data on second call to send.
Adds some nohost tests for parts.
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=13676
Includes attachements 3495, 3624, 3625
Contributed by: Adrian Sutton
Committed by: Jeff Dever
Revision Changes Path
1.3 +80 -12
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java
Index: FilePart.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- FilePart.java 11 Oct 2002 05:16:32 -0000 1.2
+++ FilePart.java 29 Oct 2002 06:40:15 -0000 1.3
@@ -64,6 +64,7 @@
import java.io.File;
import java.io.FileInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileNotFoundException;
@@ -82,6 +83,7 @@
*
* @author <a href="mailto:mattalbright@;yahoo.com">Matthew Albright</a>
* @author <a href="mailto:jsdever@;apache.org">Jeff Dever</a>
+ * @author <a href="mailto:adrian@;ephox.com">Adrian Sutton</a>
*
* @since 2.0
*
@@ -91,12 +93,17 @@
//TODO: make this configurable
static int MAX_BUFF_SIZE = 1 * 1024 * 1024; // 1 MiBs
+ private File file;
private InputStream fileStream;
private String fileName;
private long fileLength;
private String name;
private int buff_size;
+
+ private byte[] dataBuf = null;
+ private boolean bufferData = true;
+ private boolean markSupported = false;
/**
* Constructor.
@@ -110,7 +117,8 @@
public FilePart(String name, File file)
throws FileNotFoundException {
- this( name, new FileInputStream(file), file.getName(), file.length() );
+ // We create the input stream straight from the file later on.
+ this( name, null, file.getName(), file.length() );
if (! file.isFile()) {
throw new FileNotFoundException("File is not a normal file.");
@@ -119,16 +127,24 @@
if (! file.canRead()) {
throw new FileNotFoundException("File is not readable.");
}
+
+ this.file = file;
+ this.bufferData = false;
}
/**
- * FilePart Constructor.
+ * FilePart Constructor. This constructor should generally be
+ * avoided in favour of FilePart(String, java.io.File) as
+ * using an InputStream requires data to be buffered in RAM in case
+ * it needs to be resent.
*
* @param name the name for this part
* @param fileInputStream an input stream for reading the file content
* @param fileName the name of the file
* @param fileLength the number of bytes contained in the file
+ * @see #getBufferData()
+ * @see #setBufferData(boolean)
*/
public FilePart(
String name,
@@ -145,7 +161,12 @@
this.fileStream = fileInputStream;
this.fileName = fileName;
this.fileLength = fileLength;
-
+ // We need to cast fileLength to an int to call mark(int) on the
+ // input stream, so we must ensure that the file length will fit
+ // into an int before trying to use mark and reset.
+ this.markSupported = fileInputStream.markSupported() &&
+ fileLength <= Integer.MAX_VALUE;
+ this.bufferData = !markSupported;
}
protected void sendHeader(OutputStream out)
@@ -190,18 +211,65 @@
buff = new byte[(new Long(lengthOfData())).intValue()];
}
- int len;
-
- while ((len = fileStream.read(buff)) != -1)
- {
- out.write(buff, 0, len);
+ InputStream is = fileStream;
+ if (markSupported) {
+ fileStream.mark((int)fileLength);
+ }
+ if (file != null) {
+ is = new FileInputStream(file);
+ }
+ if (dataBuf != null) {
+ // Send the buffered data from a previous send.
+ out.write(dataBuf, 0, dataBuf.length);
+ } else {
+ int len;
+ ByteArrayOutputStream bufferStream = null;
+ if (bufferData) {
+ bufferStream = new ByteArrayOutputStream();
+ }
+ while ((len = is.read(buff)) != -1) {
+ out.write(buff, 0, len);
+ if (bufferData) {
+ bufferStream.write(buff, 0, len);
+ }
+ }
+ if (bufferData) {
+ dataBuf = bufferStream.toByteArray();
+ }
+ if (markSupported) {
+ fileStream.reset();
+ }
}
-
}
protected long lengthOfData()
throws IOException {
return fileLength;
}
+
+ /**
+ * Sets whether or not to buffer the data from the input stream so
+ * that it can be resent if nessecary during the connection. Note
+ * that this has no effect if this FilePart was constructed from a
+ * File object as a new FileInputStream will always be opened for
+ * each request.
+ *
+ * @param bufferData true if the data should be buffered in memory.
+ * @see #getBufferData()
+ */
+ public void setBufferData(boolean bufferData) {
+ this.bufferData = bufferData;
+ }
+
+ /**
+ * Returns whether or not data from the input stream is buffered in
+ * memory for this FilePart.
+ *
+ * @return true if the data will be buffered in memory.
+ * @see #setBufferData(boolean)
+ */
+ public boolean getBufferData() {
+ return bufferData && file == null;
+ }
}
1.14 +5 -4
jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestNoHost.java
Index: TestNoHost.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestNoHost.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- TestNoHost.java 25 Oct 2002 10:15:52 -0000 1.13
+++ TestNoHost.java 29 Oct 2002 06:40:15 -0000 1.14
@@ -100,6 +100,7 @@
suite.addTest(TestRequestHeaders.suite());
suite.addTest(TestStreams.suite());
suite.addTest(TestStatusLine.suite());
+ suite.addTest(TestPartsNoHost.suite());
return suite;
}
1.1
jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestPartsNoHost.java
Index: TestPartsNoHost.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestPartsNoHost.java,v
1.1 2002/10/29 06:40:15 jsdever Exp $
* $Revision: 1.1 $
* $Date: 2002/10/29 06:40:15 $
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.commons.httpclient;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.FileInputStream;
import java.io.File;
import java.io.PrintWriter;
import java.io.Reader;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.StringPart;
/**
* @author <a href="mailto:adrian@;ephox.com">Adrian Sutton</a>
* @version $Revision: 1.1 $ $Date: 2002/10/29 06:40:15 $
*/
public class TestPartsNoHost extends TestCase {
static final String PART_DATA = "This is the part data.";
static final String NAME = "name";
// ------------------------------------------------------------ Constructor
public TestPartsNoHost(String testName) {
super(testName);
}
// ------------------------------------------------------- TestCase Methods
public static Test suite() {
return new TestSuite(TestMethodsNoHost.class);
}
// ----------------------------------------------------------------- Tests
public void testFilePartResendsFileData() throws Exception {
File file = createTempTestFile();
FilePart part = new FilePart(NAME, file);
part.setBufferData(false); // Don't buffer in RAM.
ByteArrayOutputStream stream = new ByteArrayOutputStream();
part.send(stream);
String resp1 = stream.toString();
stream = new ByteArrayOutputStream();
part.send(stream);
String resp2 = stream.toString();
file.delete();
assertEquals(resp1, resp2);
}
public void testFilePartResendsStreamDataNoMark() throws Exception {
File file = createTempTestFile();
FileInputStream is = new FileInputStream(file);
FilePart part = new FilePart(NAME, is, file.getName(), file.length());
ByteArrayOutputStream stream = new ByteArrayOutputStream();
part.send(stream);
String resp1 = stream.toString();
stream = new ByteArrayOutputStream();
part.send(stream);
String resp2 = stream.toString();
file.delete();
assertEquals(resp1, resp2);
}
public void testFilePartResendsStreamDataWithMark() throws Exception {
byte[] byteData = PART_DATA.getBytes();
ByteArrayInputStream is = new ByteArrayInputStream(byteData);
FilePart part = new FilePart(NAME, is, NAME, byteData.length);
part.setBufferData(false);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
part.send(stream);
String resp1 = stream.toString();
stream = new ByteArrayOutputStream();
part.send(stream);
String resp2 = stream.toString();
assertEquals(resp1, resp2);
}
public void testFilePartNoBuffer() throws Exception {
File file = createTempTestFile();
FilePart part = new FilePart(NAME, file);
part.setBufferData(false);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
part.send(stream);
String resp1 = stream.toString();
stream = new ByteArrayOutputStream();
part.send(stream);
String resp2 = stream.toString();
file.delete();
assertTrue(resp2.length() < resp1.length());
}
public void testStringPartResendsData() throws Exception {
StringPart part = new StringPart(NAME, PART_DATA);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
part.send(stream);
String resp1 = stream.toString();
stream = new ByteArrayOutputStream();
String resp2 = stream.toString();
assertEquals(resp1, resp2);
}
/** Writes PART_DATA out to a temporary file and returns the file it
* was written to.
* @return the File object representing the file the data was
* written to.
*/
private File createTempTestFile() throws IOException {
File file = File.createTempFile("FilePartTest", ".txt");
PrintWriter out = new PrintWriter(new FileWriter(file));
out.println(PART_DATA);
out.flush();
out.close();
return file;
}
}
--
To unsubscribe, e-mail: <mailto:commons-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@;jakarta.apache.org>