jsdever 2002/11/10 00:09:53
Modified: httpclient/src/java/org/apache/commons/httpclient/methods/multipart
FilePart.java
httpclient/src/test/org/apache/commons/httpclient
TestPartsNoHost.java
Added: httpclient/src/java/org/apache/commons/httpclient/methods/multipart
ByteArrayPartSource.java FilePartSource.java
PartSource.java
Log:
Refactoring of MultiPartPost.
Contributed by: Michael Becke
Revision Changes Path
1.5 +28 -125
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.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- FilePart.java 5 Nov 2002 17:50:22 -0000 1.4
+++ FilePart.java 10 Nov 2002 08:09:53 -0000 1.5
@@ -63,31 +63,26 @@
package org.apache.commons.httpclient.methods.multipart;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.security.InvalidParameterException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* This class implements a part of a Multipart post object that
* consists of a file.
*
- * It makes every effort to not parse or store
- * any of the data in the file, in order to not munge a binary file,
- * and to not break if the file is huge. Hence, use a simple byte
- * array, and just shove it down the OutputStream.
- *
* @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
+ * @author <a href="mailto:becke@;u.washington.edu">Michael Becke</a>
+ *
+ * @since 2.0
*
*/
public class FilePart extends Part {
@@ -98,82 +93,41 @@
//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;
+ private PartSource source;
/**
- * Constructor.
+ * FilePart Constructor.
*
* @param name
* @param file the file to post
*
- * @throws FileNotFoundException if the <i>file</i> is not is normal
+ * @throws FileNotFoundException if the <i>file</i> is not a normal
* file or if it is not readable.
*/
public FilePart(String name, File file)
throws FileNotFoundException {
-
- // 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.");
- }
-
- if (! file.canRead()) {
- throw new FileNotFoundException("File is not readable.");
- }
-
- this.file = file;
- this.bufferData = false;
-
+ this( name, new FilePartSource( file ) );
}
/**
- * 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.
+ * FilePart Constructor.
*
* @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)
+ * @param partSource the source for this part
*/
public FilePart(
String name,
- InputStream fileInputStream,
- String fileName,
- long fileLength
+ PartSource partSource
) {
- if ( fileLength < 0 ) {
+ if ( partSource.getLength() < 0 ) {
throw new InvalidParameterException( "fileLength must be >= 0." );
}
this.name = name;
- 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.
- if (fileInputStream != null) {
- this.markSupported = fileInputStream.markSupported() &&
- fileLength <= Integer.MAX_VALUE;
- this.bufferData = !markSupported;
- }
+ this.source = partSource;
+
}
protected void sendHeader(OutputStream out)
@@ -187,7 +141,7 @@
protected void sendFilename(OutputStream out)
throws IOException {
log.trace("enter sendFilename(OutputStream out)");
- String filename = "; filename=\"" + fileName + "\"";
+ String filename = "; filename=\"" + source.getFileName() + "\"";
out.write(filename.getBytes());
}
@@ -223,70 +177,19 @@
buff = new byte[(new Long(lengthOfData())).intValue()];
}
- InputStream is = fileStream;
- if (markSupported) {
- fileStream.mark((int)fileLength);
- }
- if (file != null) {
- is = new FileInputStream(file);
- dataBuf = null;
- }
- 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();
- }
- }
- if (file != null) {
- is.close();
+ InputStream is = source.createInputStream();
+
+ int len;
+ while ((len = is.read(buff)) != -1) {
+ out.write(buff, 0, len);
}
+
}
protected long lengthOfData()
throws IOException {
- return fileLength;
+ return source.getLength();
}
- /**
- * 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) {
- log.trace("enter 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.1
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/ByteArrayPartSource.java
Index: ByteArrayPartSource.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/ByteArrayPartSource.java,v
1.1 2002/11/10 08:09:53 jsdever Exp $
* $Revision: 1.1 $
* $Date: 2002/11/10 08:09:53 $
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 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.methods.multipart;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* A PartSource that reads from a byte array. This class should be used when
* the data to post is already loaded into memory.
*
* @author <a href="mailto:becke@;u.washington.edu">Michael Becke</a>
*
* @since 2.0
*/
public class ByteArrayPartSource implements PartSource {
private String fileName;
private byte[] bytes;
/**
* Constructor for ByteArrayPartSource.
*
* @param fileName the name of the file these bytes represent
* @param bytes the content of this part
*/
public ByteArrayPartSource( String fileName, byte[] bytes ) {
this.fileName = fileName;
this.bytes = bytes;
}
/**
* @see org.apache.commons.httpclient.methods.multipart.PartSource#getLength()
*/
public long getLength() {
return bytes.length;
}
/**
* @see org.apache.commons.httpclient.methods.multipart.PartSource#getName()
*/
public String getFileName() {
return fileName;
}
/**
* @see
org.apache.commons.httpclient.methods.multipart.PartSource#createInputStream()
*/
public InputStream createInputStream() throws IOException {
return new ByteArrayInputStream( bytes );
}
}
1.1
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePartSource.java
Index: FilePartSource.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePartSource.java,v
1.1 2002/11/10 08:09:53 jsdever Exp $
* $Revision: 1.1 $
* $Date: 2002/11/10 08:09:53 $
* ====================================================================
*
* 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.methods.multipart;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* A PartSource that reads from a File.
*
* @author <a href="mailto:becke@;u.washington.edu">Michael Becke</a>
*
* @since 2.0
*/
public class FilePartSource implements PartSource {
private File file;
/**
* Constructor for FilePartSource.
*
* @exception FileNotFoundException if the file does not exist or
* cannot be read
*/
public FilePartSource( File file ) throws FileNotFoundException {
if (! file.isFile()) {
throw new FileNotFoundException("File is not a normal file.");
}
if (! file.canRead()) {
throw new FileNotFoundException("File is not readable.");
}
this.file = file;
}
/**
* @see org.apache.commons.httpclient.methods.multipart.PartSource#getLength()
*/
public long getLength() {
return file.length();
}
/**
* @see org.apache.commons.httpclient.methods.multipart.PartSource#getName()
*/
public String getFileName() {
return file.getName();
}
/**
* @see
org.apache.commons.httpclient.methods.multipart.PartSource#createInputStream()
*/
public InputStream createInputStream() throws IOException {
return new FileInputStream( file );
}
}
1.1
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/PartSource.java
Index: PartSource.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/PartSource.java,v
1.1 2002/11/10 08:09:53 jsdever Exp $
* $Revision: 1.1 $
* $Date: 2002/11/10 08:09:53 $
* ====================================================================
*
* 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.methods.multipart;
import java.io.IOException;
import java.io.InputStream;
/**
* An interface for providing access to data when posting MultiPart messages.
*
* @see org.apache.commons.httpclient.methods.multipart.FilePart
* @see org.apache.commons.httpclient.methods.MultipartPostMethod#addPart(Part)
*
* @author <a href="mailto:becke@;u.washington.edu">Michael Becke</a>
*
* @since 2.0
*/
public interface PartSource {
/**
* Gets the number of bytes contained in this source.
*
* @return a value >= 0
*/
public long getLength();
/**
* Gets the name of the file this source represents.
*
* @return the fileName used for posting a MultiPart file part
*/
public String getFileName();
/**
* Gets a new InputStream for reading this source. This method can be called
* more than once and should therefore return a new stream every time.
*
* @return a new InputStream
*
* @exception IOException if an error occurs when creating the InputStream
*/
public InputStream createInputStream() throws IOException;
}
1.3 +4 -48
jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestPartsNoHost.java
Index: TestPartsNoHost.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestPartsNoHost.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- TestPartsNoHost.java 5 Nov 2002 17:50:22 -0000 1.2
+++ TestPartsNoHost.java 10 Nov 2002 08:09:53 -0000 1.3
@@ -104,7 +104,6 @@
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();
@@ -113,49 +112,6 @@
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,
- new FileInputStream(file), file.getName(), file.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();
- file.delete();
- assertTrue(resp2.length() < resp1.length());
}
public void testStringPartResendsData() throws Exception {
--
To unsubscribe, e-mail: <mailto:commons-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@;jakarta.apache.org>