Jeff, Wire, WireLogOutputStream, WireLogInputStream classes need to be accessible by classes from the following packages: org.apache.commons.httpclient org.apache.commons.httpclient.methods org.apache.commons.httpclient.methods.multipart
Making wire logging related classes non-public does not seem feasible with the present package structure. Cheers Oleg On Tue, 2003-02-11 at 04:19, Jeffrey Dever wrote: > I like the refactoring. Only complaint is that the classes are public. > Package access would be prefered, but this may not be possible. > > > Oleg Kalnichevski wrote: > > >Fixes the following bugs: > > > >http://nagoya.apache.org/bugzilla/show_bug.cgi?id=14782 > > > >Change log: > >- MultipartPost related methods clean-up > >- Part#send(OutputStream out) & long Part#length() are no more final > >- Content encoding can be specified > >- FilePart's content type can be specified > >- FilePart's transfer encoding can be specified > >- Wire logging improvement > > > >While working on multi-part post stuff I have been through many pains > >debugging modified classes and trying to figure out what exactly gets > >sent to the server. Currently wire logging can be regarded as > >inconsistent at best. In those parts where wire logging is implemented I > >find it not particularly visually appealing. While "scratching my own > >itch" I have taken liberty of rewriting wire logging. Please comment if > >you find these changes acceptable. Suggestions on possible improvements > >are welcome. > > > >To be done next: > > > >- Fix bug #14036 > >- Apply new wire logging consistently throughout the HttpClient codebase > >(provided new wire logging meets your approval) > > > > > >------------------------------------------------------------------------ > > > >Index: src/java/org/apache/commons/httpclient/HttpConnection.java > >=================================================================== > >RCS file: >/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v > >retrieving revision 1.42 > >diff -u -r1.42 HttpConnection.java > >--- src/java/org/apache/commons/httpclient/HttpConnection.java 8 Feb 2003 >19:22:49 -0000 1.42 > >+++ src/java/org/apache/commons/httpclient/HttpConnection.java 10 Feb 2003 >22:02:08 -0000 > >@@ -75,6 +75,7 @@ > > import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; > > import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; > > import org.apache.commons.httpclient.util.TimeoutController; > >+import org.apache.commons.httpclient.util.Wire; > > import org.apache.commons.logging.Log; > > import org.apache.commons.logging.LogFactory; > > > >@@ -727,9 +728,8 @@ > > > > assertOpen(); > > > >- if (WIRE_LOG.isDebugEnabled()) { > >- String dataString = new String(data, offset, length, "ISO-8859-1"); > >- WIRE_LOG.debug(">> \"" + dataString + "\" [\\r\\n]"); > >+ if (Wire.enabled()) { > >+ Wire.output(data, offset, length, HttpConstants.HTTP_ELEMENT_CHARSET); > > } > > try { > > outputStream.write(data, offset, length); > >@@ -758,9 +758,8 @@ > > LOG.trace("enter HttpConnection.writeLine(byte[])"); > > > > assertOpen(); > >- if (WIRE_LOG.isDebugEnabled() && (data.length > 0)) { > >- String dataString = HttpConstants.getContentString(data); > >- WIRE_LOG.debug(">> \"" + dataString.trim() + "\" [\\r\\n]"); > >+ if (Wire.enabled()) { > >+ Wire.output(data, HttpConstants.HTTP_ELEMENT_CHARSET); > > } > > try { > > outputStream.write(data); > >@@ -786,7 +785,9 @@ > > throws IOException, IllegalStateException, HttpRecoverableException { > > LOG.trace("enter HttpConnection.writeLine()"); > > > >- WIRE_LOG.debug(">> [\\r\\n]"); > >+ if (Wire.enabled()) { > >+ Wire.output(CRLF, HttpConstants.HTTP_ELEMENT_CHARSET); > >+ } > > try { > > outputStream.write(CRLF); > > } catch (SocketException se) { > >@@ -871,8 +872,8 @@ > > buf.append((char) ch); > > ch = inputStream.read(); > > } > >- if (WIRE_LOG.isDebugEnabled()) { > >- WIRE_LOG.debug("<< \"" + buf.toString() + (ch>0 ? "\" [\\r\\n]" : "")); > >+ if (Wire.enabled()) { > >+ Wire.input(HttpConstants.getBytes(buf.toString()), >HttpConstants.HTTP_ELEMENT_CHARSET); > > } > > return (buf.toString()); > > } > >@@ -1059,9 +1060,6 @@ > > > > /** Log object for this class. */ > > private static final Log LOG = LogFactory.getLog(HttpConnection.class); > >- > >- /** Log for any wire messages. */ > >- private static final Log WIRE_LOG = LogFactory.getLog("httpclient.wire"); > > > > // ----------------------------------------------------- Instance Variables > > /** My host. */ > >Index: src/java/org/apache/commons/httpclient/HttpMethodBase.java > >=================================================================== > >RCS file: >/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v > >retrieving revision 1.110 > >diff -u -r1.110 HttpMethodBase.java > >--- src/java/org/apache/commons/httpclient/HttpMethodBase.java 8 Feb 2003 >19:22:49 -0000 1.110 > >+++ src/java/org/apache/commons/httpclient/HttpMethodBase.java 10 Feb 2003 >22:02:13 -0000 > >@@ -1752,7 +1752,7 @@ > > Header transferEncodingHeader = getResponseHeader("Transfer-Encoding"); > > InputStream is = conn.getResponseInputStream(); > > if (WIRE_LOG.isDebugEnabled()) { > >- is = new WireLogInputStream(is); > >+ is = new WireLogInputStream(is, getResponseCharSet()); > > } > > InputStream result = null; > > // We use Transfer-Encoding if present and ignore Content-Length. > >Index: src/java/org/apache/commons/httpclient/WireLogInputStream.java > >=================================================================== > >RCS file: >/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/WireLogInputStream.java,v > >retrieving revision 1.8 > >diff -u -r1.8 WireLogInputStream.java > >--- src/java/org/apache/commons/httpclient/WireLogInputStream.java 31 Jan 2003 >00:33:36 -0000 1.8 > >+++ src/java/org/apache/commons/httpclient/WireLogInputStream.java 10 Feb 2003 >22:02:13 -0000 > >@@ -68,26 +68,38 @@ > > import java.io.InputStream; > > import org.apache.commons.logging.Log; > > import org.apache.commons.logging.LogFactory; > >+import org.apache.commons.httpclient.util.Wire; > > > > /** > > * Logs all data read to the wire LOG. > > * > > * @author Ortwin Gl?¿? > > * @author <a href="mailto:[EMAIL PROTECTED]">Mike Bowler</a> > >+ * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Kalnichevski</a> > > * > > * @since 2.0 > > */ > > > > class WireLogInputStream extends FilterInputStream { > >+ > > /** Log for any wire messages. */ > > private static final Log WIRE_LOG = LogFactory.getLog("httpclient.wire"); > > > >+ /** Content encoding. */ > >+ private String charset = "US-ASCII"; > >+ > >+ /** Original input stream. */ > >+ private InputStream in; > > /** > > * Create an instance that wraps the specified input stream. > > * @param in The input stream. > > */ > >- public WireLogInputStream(InputStream in) { > >+ public WireLogInputStream(InputStream in, String charset) { > > super(in); > >+ if (charset != null) { > >+ this.charset = charset; > >+ } > >+ this.in = in; > > } > > > > /** > >@@ -95,8 +107,10 @@ > > * @see java.io.InputStream#read(byte[], int, int) > > */ > > public int read(byte[] b, int off, int len) throws IOException { > >- int l = super.read(b, off, len); > >- WIRE_LOG.debug("<< " + new String(b, off, len)); > >+ int l = this.in.read(b, off, len); > >+ if (l > 0) { > >+ Wire.input(b, off, len, null); > >+ } > > return l; > > } > > > >@@ -105,9 +119,9 @@ > > * @see java.io.InputStream#read() > > */ > > public int read() throws IOException { > >- int l = super.read(); > >+ int l = this.in.read(); > > if (l > 0) { > >- WIRE_LOG.debug("<< " + (char) l); > >+ Wire.input(l, null); > > } > > return l; > > } > >@@ -117,8 +131,10 @@ > > * @see java.io.InputStream#read(byte[]) > > */ > > public int read(byte[] b) throws IOException { > >- int l = super.read(b); > >- WIRE_LOG.debug("<< " + HttpConstants.getString(b)); > >+ int l = this.in.read(b); > >+ if (l > 0) { > >+ Wire.input(b, null); > >+ } > > return l; > > } > > } > >Index: src/java/org/apache/commons/httpclient/WireLogOutputStream.java > >=================================================================== > >RCS file: src/java/org/apache/commons/httpclient/WireLogOutputStream.java > >diff -N src/java/org/apache/commons/httpclient/WireLogOutputStream.java > >--- /dev/null 1 Jan 1970 00:00:00 -0000 > >+++ src/java/org/apache/commons/httpclient/WireLogOutputStream.java 10 Feb 2003 >22:02:14 -0000 > >@@ -0,0 +1,132 @@ > >+/* > >+ * ==================================================================== > >+ * > >+ * The Apache Software License, Version 1.1 > >+ * > >+ * Copyright (c) 1999-2003 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", "Commons", 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.FilterOutputStream; > >+import java.io.IOException; > >+import java.io.InputStream; > >+import java.io.OutputStream; > >+import java.io.ByteArrayInputStream; > >+import java.io.Reader; > >+import java.io.InputStreamReader; > >+import java.io.BufferedReader; > >+import java.io.UnsupportedEncodingException; > >+import org.apache.commons.logging.Log; > >+import org.apache.commons.logging.LogFactory; > >+import org.apache.commons.httpclient.util.Wire; > >+ > >+/** > >+ * Logs all data written to the wire LOG. > >+ * > >+ * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Kalnichevski</a> > >+ * > >+ * @since 2.0beta1 > >+ */ > >+ > >+public class WireLogOutputStream extends FilterOutputStream { > >+ > >+ /** Log for any wire messages. */ > >+ private static final Log WIRE_LOG = LogFactory.getLog("httpclient.wire"); > >+ > >+ /** Content encoding. */ > >+ private String charset = "US-ASCII"; > >+ > >+ /** Original input stream. */ > >+ private OutputStream out; > >+ > >+ /** > >+ * Create an instance that wraps the specified output stream. > >+ * @param out The output stream. > >+ */ > >+ public WireLogOutputStream(OutputStream out, String charset) { > >+ super(out); > >+ if (charset != null) { > >+ this.charset = charset; > >+ } > >+ this.out = out; > >+ } > >+ > >+ /** > >+ * > >+ * @see java.io.OutputStream#write(byte[], int, int) > >+ */ > >+ public void write(byte[] b, int off, int len) throws IOException { > >+ this.out.write(b, off, len); > >+ Wire.output(b, off, len, this.charset); > >+ } > >+ > >+ /** > >+ * > >+ * @see java.io.OutputStream#write() > >+ */ > >+ public void write(int b) throws IOException { > >+ this.out.write(b); > >+ Wire.output(b, this.charset); > >+ } > >+ > >+ /** > >+ * > >+ * @see java.io.OutputStream#write(byte[]) > >+ */ > >+ public void write(byte[] b) throws IOException { > >+ this.out.write(b); > >+ Wire.output(b, this.charset); > >+ } > >+} > >Index: src/java/org/apache/commons/httpclient/methods/MultipartPostMethod.java > >=================================================================== > >RCS file: >/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/MultipartPostMethod.java,v > >retrieving revision 1.8 > >diff -u -r1.8 MultipartPostMethod.java > >--- src/java/org/apache/commons/httpclient/methods/MultipartPostMethod.java 2 Feb >2003 04:30:13 -0000 1.8 > >+++ src/java/org/apache/commons/httpclient/methods/MultipartPostMethod.java 10 Feb >2003 22:02:15 -0000 > >@@ -94,6 +94,10 @@ > > */ > > public class MultipartPostMethod extends GetMethod { > > > >+ /** The Content-Type for multipart/form-data. */ > >+ public static final String MULTIPART_FORM_CONTENT_TYPE = > >+ "multipart/form-data"; > >+ > > /** Log object for this class. */ > > private static final Log LOG = LogFactory.getLog(MultipartPostMethod.class); > > > >@@ -204,6 +208,14 @@ > > } > > > > /** > >+ * Return all parts. > >+ * > >+ * @return an array of containing all parts > >+ */ > >+ public Part[] getParts() { > >+ return (Part[])parameters.toArray(new Part[parameters.size()]); > >+ } > >+ /** > > * Add a request header. > > * > > * @param state the client state > >@@ -218,8 +230,12 @@ > > super.addRequestHeaders(state, conn); > > > > if (!parameters.isEmpty()) { > >- setRequestHeader("Content-Type", > >- "multipart/form-data; boundary=" + Part.getBoundary()); > >+ StringBuffer buffer = new StringBuffer(MULTIPART_FORM_CONTENT_TYPE); > >+ if (Part.getBoundary() != null) { > >+ buffer.append("; boundary="); > >+ buffer.append(Part.getBoundary()); > >+ } > >+ setRequestHeader("Content-Type", buffer.toString()); > > } > > } > > > >@@ -237,16 +253,7 @@ > > throws IOException, HttpException { > > LOG.trace("enter writeRequestBody(HttpState state, HttpConnection conn)"); > > OutputStream out = conn.getRequestOutputStream(); > >- > >- for (Iterator it = parameters.iterator(); it.hasNext();) { > >- final Part part = (Part) it.next(); > >- part.send(out); > >- } > >- > >- Part.sendLastBoundary(out); > >- > >- out.flush(); > >- > >+ Part.sendParts(out, getParts()); > > return true; > > } > > > >@@ -260,26 +267,17 @@ > > */ > > protected int getRequestContentLength() { > > LOG.trace("enter getRequestContentLength()"); > >- long length = 0; > >- > > try { > >- for (Iterator it = parameters.iterator(); it.hasNext();) { > >- final Part part = (Part) it.next(); > >- > >- length += part.length(); > >+ long len = Part.getLengthOfParts(getParts()); > >+ // Chop the length to the max int value. > >+ if (len <= Integer.MAX_VALUE) { > >+ return (int)len; > >+ } else { > >+ return (Integer.MAX_VALUE); > > } > >- length += Part.lengthOfLastBoundary(); > >- > > } catch (IOException e) { > > // Can't throw an IOException and still override > > throw new RuntimeException(e.toString()); > >- } > >- > >- // Chop the length to the max int value. > >- if (length <= Integer.MAX_VALUE) { > >- return ((new Long(length)).intValue()); > >- } else { > >- return (Integer.MAX_VALUE); > > } > > } > > } > >Index: src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java > >=================================================================== > >RCS file: >/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java,v > >retrieving revision 1.10 > >diff -u -r1.10 FilePart.java > >--- src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java 28 Jan >2003 22:25:31 -0000 1.10 > >+++ src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java 10 Feb >2003 22:02:15 -0000 > >@@ -82,27 +82,84 @@ > > * @author <a href="mailto:[EMAIL PROTECTED]">Michael Becke</a> > > * @author <a href="mailto:[EMAIL PROTECTED]">Mark Diggory</a> > > * @author <a href="mailto:[EMAIL PROTECTED]">Mike Bowler</a> > >+ * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Kalnichevski</a> > > * > > * @since 2.0 > > * > > */ > > public class FilePart extends Part { > > > >+ /** Default content encoding of file attachments. */ > >+ public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; > >+ > >+ /** Default charset of file attachments. */ > >+ public static final String DEFAULT_CHARSET = >HttpConstants.DEFAULT_CONTENT_CHARSET; > >+ > >+ /** Default transfer encoding of file attachments. */ > >+ public static final String DEFAULT_TRANSFER_ENCODING = "binary"; > >+ > > /** Log object for this class. */ > > private static final Log LOG = LogFactory.getLog(FilePart.class); > > > >- /** > >- * <p>The maximum buffer size.</p> > >- * TODO: make this configurable > >- */ > >- private static final int MAX_BUFF_SIZE = 1 * 1024 * 1024; // 1 MiBs > >- > >+ > >+ /** Attachment's file name */ > >+ protected static final String FILE_NAME = "; filename="; > >+ > >+ /** Attachment's file name as a byte array */ > >+ protected static final byte[] FILE_NAME_BYTES = > >+ HttpConstants.getAsciiBytes(FILE_NAME); > >+ > > /** Name of the file part. */ > > private String name; > > > > /** Source of the file part. */ > > private PartSource source; > > > >+ /** Content type of the file part. */ > >+ private String contentType; > >+ > >+ /** Content encoding of the file part. */ > >+ private String charset; > >+ > >+ /** > >+ * FilePart Constructor. > >+ * > >+ * @param name the name for this part > >+ * @param partSource the source for this part > >+ * @param contentType the content type for this part > >+ * @param charset the charset encoding for this part > >+ */ > >+ public FilePart(String name, PartSource partSource, String contentType, String >charset) { > >+ LOG.trace("enter FilePart(String, PartSource, String, String)"); > >+ if (name == null) { > >+ throw new IllegalArgumentException("Name may not be null"); > >+ } > >+ this.name = name; > >+ if (partSource == null) { > >+ throw new IllegalArgumentException("Source may not be null"); > >+ } > >+ if (partSource.getLength() < 0) { > >+ throw new IllegalArgumentException("Source length must be >= 0"); > >+ } > >+ this.source = partSource; > >+ if (contentType != null) { > >+ this.contentType = contentType; > >+ } else { > >+ this.contentType = DEFAULT_CONTENT_TYPE; > >+ } > >+ this.charset = charset; > >+ } > >+ > >+ /** > >+ * FilePart Constructor. > >+ * > >+ * @param name the name for this part > >+ * @param partSource the source for this part > >+ */ > >+ public FilePart(String name, PartSource partSource) { > >+ this(name, partSource, null, null); > >+ } > >+ > > /** > > * FilePart Constructor. > > * > >@@ -114,7 +171,23 @@ > > */ > > public FilePart(String name, File file) > > throws FileNotFoundException { > >- this(name, new FilePartSource(file)); > >+ this(name, new FilePartSource(file), null, null); > >+ } > >+ > >+ /** > >+ * FilePart Constructor. > >+ * > >+ * @param name the name of the file part > >+ * @param file the file to post > >+ * @param contentType the content type for the file > >+ * @param charset the charset encoding of the file > >+ * > >+ * @throws FileNotFoundException if the <i>file</i> is not a normal > >+ * file or if it is not readable. > >+ */ > >+ public FilePart(String name, File file, String contentType, String charset) > >+ throws FileNotFoundException { > >+ this(name, new FilePartSource(file), contentType, charset); > > } > > > > /** > >@@ -129,71 +202,77 @@ > > */ > > public FilePart(String name, String fileName, File file) > > throws FileNotFoundException { > >- this(name, new FilePartSource(fileName, file)); > >+ this(name, new FilePartSource(fileName, file), null, null); > > } > > > >- /** > >+ /** > > * FilePart Constructor. > > * > >- * @param name the name for this part > >- * @param partSource the source for this part > >+ * @param name the name of the file part > >+ * @param fileName the file name > >+ * @param file the file to post > >+ * @param contentType the content type for the file > >+ * @param charset the charset encoding of the file > >+ * > >+ * @throws FileNotFoundException if the <i>file</i> is not a normal > >+ * file or if it is not readable. > > */ > >- public FilePart(String name, PartSource partSource) { > >- > >- if (partSource.getLength() < 0) { > >- throw new IllegalArgumentException("fileLength must be >= 0"); > >- } > >- > >- this.name = name; > >- this.source = partSource; > >- > >+ public FilePart(String name, String fileName, File file, String contentType, >String charset) > >+ throws FileNotFoundException { > >+ this(name, new FilePartSource(fileName, file), contentType, charset); > > } > >- > >+ > > /** > >- * Write the header to the output stream > >- * @param out The output stream > >- * @throws IOException If an IO problem occurs > >- * @see >org.apache.commons.httpclient.methods.multipart.Part#sendHeader(OutputStream) > >+ * Return the name. > >+ * @return The name. > >+ * @see org.apache.commons.httpclient.methods.multipart.Part#getName() > > */ > >- protected void sendHeader(OutputStream out) > >- throws IOException { > >- LOG.trace("enter sendHeader(OutputStream out)"); > >- super.sendHeader(out); > >- sendFilename(out); > >- sendContentType(out); > >+ public String getName() { > >+ return this.name; > > } > >- > >+ > > /** > >- * Write the filename to the output stream > >- * @param out The output stream > >- * @throws IOException If an IO problem occurs > >+ * Return the content type of this part. > >+ * @return String The name. > > */ > >- protected void sendFilename(OutputStream out) > >- throws IOException { > >- LOG.trace("enter sendFilename(OutputStream out)"); > >- String filename = "; filename=\"" + source.getFileName() + "\""; > >- out.write(HttpConstants.getBytes(filename)); > >+ public String getContentType() { > >+ return this.contentType; > > } > > > > /** > >- * Write the Content-Type header to the output stream > >- * @param out The output stream. > >- * @throws IOException If an IO problem occurs > >+ * Return the character encoding of this part. > >+ * @return String The name. > > */ > >- protected void sendContentType(OutputStream out) > >- throws IOException { > >- LOG.trace("enter sendContentType(OutputStream out)"); > >- out.write(CRLF_BYTES); > >- out.write(HttpConstants.getBytes("Content-Type: >application/octet-stream")); > >- } > >+ public String getCharSet() { > >+ return this.charset; > >+ } > > > > /** > >- * Return the name. > >- * @return The name. > >- * @see org.apache.commons.httpclient.methods.multipart.Part#getName() > >+ * Return the transfer encoding of this part. > >+ * @return String The name. > > */ > >- public String getName() { > >- return name; > >+ > >+ public String getTransferEncoding() { > >+ return DEFAULT_TRANSFER_ENCODING; > >+ } > >+ > >+ /** > >+ * Write the disposition header to the output stream > >+ * @param out The output stream > >+ * @throws IOException If an IO problem occurs > >+ * @see >org.apache.commons.httpclient.methods.multipart.Part#sendHeader(OutputStream) > >+ */ > >+ protected void sendDispositionHeader(OutputStream out) > >+ throws IOException { > >+ LOG.trace("enter sendDispositionHeader(OutputStream out)"); > >+ super.sendDispositionHeader(out); > >+ String filename = this.source.getFileName(); > >+ if (filename != null) { > >+ out.write(FILE_NAME_BYTES); > >+ out.write(QUOTE_BYTES); > >+ out.write(HttpConstants.getAsciiBytes(filename)); > >+ out.write(QUOTE_BYTES); > >+ } > > } > > > > /** > >@@ -204,9 +283,6 @@ > > */ > > protected void sendData(OutputStream out) throws IOException { > > LOG.trace("enter sendData(OutputStream out)"); > >- > >- byte[] buff; > >- > > if (lengthOfData() == 0) { > > > > // this file contains no data, so there is nothing to send. > >@@ -214,20 +290,15 @@ > > // cause an infinite loop when reading. > > LOG.debug("No data to send."); > > return; > >- > >- } else if (lengthOfData() > MAX_BUFF_SIZE) { > >- buff = new byte[MAX_BUFF_SIZE]; > >- } else { > >- buff = new byte[(new Long(lengthOfData())).intValue()]; > > } > > > >- InputStream is = source.createInputStream(); > >+ byte[] tmp = new byte[4096]; > >+ InputStream instream = source.createInputStream(); > > > > int len; > >- while ((len = is.read(buff)) != -1) { > >- out.write(buff, 0, len); > >+ while ((len = instream.read(tmp)) >= 0) { > >+ out.write(tmp, 0, len); > > } > >- > > } > > > > /** > >@@ -237,8 +308,8 @@ > > * @see org.apache.commons.httpclient.methods.multipart.Part#lengthOfData() > > */ > > protected long lengthOfData() throws IOException { > >+ LOG.trace("enter lengthOfData()"); > > return source.getLength(); > > } > > > >-} > >- > >+} > >\ No newline at end of file > >Index: src/java/org/apache/commons/httpclient/methods/multipart/Part.java > >=================================================================== > >RCS file: >/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/Part.java,v > >retrieving revision 1.7 > >diff -u -r1.7 Part.java > >--- src/java/org/apache/commons/httpclient/methods/multipart/Part.java 28 Jan >2003 22:25:31 -0000 1.7 > >+++ src/java/org/apache/commons/httpclient/methods/multipart/Part.java 10 Feb >2003 22:02:16 -0000 > >@@ -63,10 +63,13 @@ > > > > package org.apache.commons.httpclient.methods.multipart; > > > >+import java.io.IOException; > > import java.io.OutputStream; > >+import java.io.ByteArrayInputStream; > > import java.io.ByteArrayOutputStream; > >-import java.io.IOException; > >+ > > import org.apache.commons.httpclient.HttpConstants; > >+import org.apache.commons.httpclient.WireLogOutputStream; > > import org.apache.commons.logging.Log; > > import org.apache.commons.logging.LogFactory; > > > >@@ -77,6 +80,7 @@ > > * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Dever</a> > > * @author <a href="mailto:[EMAIL PROTECTED]">Adrian Sutton</a> > > * @author <a href="mailto:[EMAIL PROTECTED]">Mike Bowler</a> > >+ * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Kalnichevski</a> > > * > > * @since 2.0 > > */ > >@@ -85,26 +89,65 @@ > > /** Log object for this class. */ > > private static final Log LOG = LogFactory.getLog(Part.class); > > > >+ /** Log for any wire messages. */ > >+ private static final Log WIRE_LOG = LogFactory.getLog("httpclient.wire"); > >+ > > //TODO: Make this configurable > > > > /** The boundary */ > >- private static final String BOUNDARY = "----------------314159265358979323846"; > >+ protected static final String BOUNDARY = >"----------------314159265358979323846"; > > > > /** The boundary as a byte array */ > >- private static final byte[] BOUNDARY_BYTES = HttpConstants.getBytes(BOUNDARY); > >+ protected static final byte[] BOUNDARY_BYTES = >HttpConstants.getAsciiBytes(BOUNDARY); > > > > /** Carriage return/linefeed */ > >- private static final String CRLF = "\r\n"; > >+ protected static final String CRLF = "\r\n"; > > > > /** Carriage return/linefeed as a byte array */ > >- protected static final byte[] CRLF_BYTES = HttpConstants.getBytes(CRLF); > >+ protected static final byte[] CRLF_BYTES = HttpConstants.getAsciiBytes(CRLF); > > > >+ /** Content dispostion characters */ > >+ protected static final String QUOTE = "\""; > >+ > >+ /** Content dispostion as a byte array */ > >+ protected static final byte[] QUOTE_BYTES = > >+ HttpConstants.getAsciiBytes(QUOTE); > >+ > > /** Extra characters */ > >- private static final String EXTRA = "--"; > >+ protected static final String EXTRA = "--"; > > > > /** Extra characters as a byte array */ > >- private static final byte[] EXTRA_BYTES = HttpConstants.getBytes(EXTRA); > >+ protected static final byte[] EXTRA_BYTES = > >+ HttpConstants.getAsciiBytes(EXTRA); > >+ > >+ /** Content dispostion characters */ > >+ protected static final String CONTENT_DISPOSITION = "Content-Disposition: >form-data; name="; > > > >+ /** Content dispostion as a byte array */ > >+ protected static final byte[] CONTENT_DISPOSITION_BYTES = > >+ HttpConstants.getAsciiBytes(CONTENT_DISPOSITION); > >+ > >+ /** Content type header */ > >+ protected static final String CONTENT_TYPE = "Content-Type: "; > >+ > >+ /** Content type header as a byte array */ > >+ protected static final byte[] CONTENT_TYPE_BYTES = > >+ HttpConstants.getAsciiBytes(CONTENT_TYPE); > >+ > >+ /** Content charset */ > >+ protected static final String CHARSET = "; charset="; > >+ > >+ /** Content charset as a byte array */ > >+ protected static final byte[] CHARSET_BYTES = > >+ HttpConstants.getAsciiBytes(CHARSET); > >+ > >+ /** Content type header */ > >+ protected static final String CONTENT_TRANSFER_ENCODING = >"Content-Transfer-Encoding: "; > >+ > >+ /** Content type header as a byte array */ > >+ protected static final byte[] CONTENT_TRANSFER_ENCODING_BYTES = > >+ HttpConstants.getAsciiBytes(CONTENT_TRANSFER_ENCODING); > >+ > > /** > > * Return the boundary string. > > * @return the boundary string > >@@ -114,40 +157,29 @@ > > } > > > > /** > >- * Write the last boundary to the specified output stream > >- * @param out The output stream > >- * @throws IOException If an IO problem occurs. > >+ * Return the name of this part. > >+ * @return String The name. > > */ > >- public static void sendLastBoundary(OutputStream out) > >- throws IOException { > >- LOG.trace("enter sendLastBoundary(OutputStream out)"); > >- out.write(EXTRA_BYTES); > >- out.write(BOUNDARY_BYTES); > >- out.write(EXTRA_BYTES); > >- out.write(CRLF_BYTES); > >- } > >+ public abstract String getName(); > > > > /** > >- * Return the length of the last boundary string > >- * > >- * @return int The length of the last boundary string > >- * @throws IOException If an IO problem occurs > >+ * Return the content type of this part. > >+ * @return String The name. > > */ > >- public static int lengthOfLastBoundary() throws IOException { > >- LOG.trace("enter lengthOfLastBoundary()"); > >- ByteArrayOutputStream out = new ByteArrayOutputStream(); > >- > >- sendLastBoundary(out); > >- > >- return out.size(); > >- } > >- > >+ public abstract String getContentType(); > >+ > > /** > >- * Return the name of this part. > >+ * Return the character encoding of this part. > > * @return String The name. > > */ > >- public abstract String getName(); > >- > >+ public abstract String getCharSet(); > >+ > >+ /** > >+ * Return the transfer encoding of this part. > >+ * @return String The name. > >+ */ > >+ public abstract String getTransferEncoding(); > >+ > > /** > > * Write the start to the specified output stream > > * @param out The output stream > >@@ -161,44 +193,58 @@ > > } > > > > /** > >- * Return the length of the starting data > >- * @return int The length of the data > >- * @throws IOException If an IO problem occurs > >+ * Write the content disposition header to the specified output stream > >+ * > >+ * @param out The output stream > >+ * @throws IOException If an IO problem occurs. > > */ > >- protected int lengthOfStart() throws IOException { > >- LOG.trace("enter lengthOfStart()"); > >- ByteArrayOutputStream out = new ByteArrayOutputStream(); > >- sendStart(out); > >- return out.size(); > >+ protected void sendDispositionHeader(OutputStream out) throws IOException { > >+ LOG.trace("enter sendDispositionHeader(OutputStream out)"); > >+ out.write(CONTENT_DISPOSITION_BYTES); > >+ out.write(QUOTE_BYTES); > >+ out.write(HttpConstants.getAsciiBytes(getName())); > >+ out.write(QUOTE_BYTES); > > } > > > > /** > >- * Write the header to the specified output stream > >+ * Write the content type header to the specified output stream > > * @param out The output stream > > * @throws IOException If an IO problem occurs. > > */ > >- protected void sendHeader(OutputStream out) throws IOException { > >- LOG.trace("enter sendHeader(OutputStream out)"); > >- String contentDisposition = "Content-Disposition: form-data; name=\"" > >- + getName() + "\""; > >- > >- out.write(HttpConstants.getBytes(contentDisposition)); > >+ > >+ protected void sendContentTypeHeader(OutputStream out) throws IOException { > >+ LOG.trace("enter sendContentTypeHeader(OutputStream out)"); > >+ String contentType = getContentType(); > >+ if (contentType != null) { > >+ out.write(CRLF_BYTES); > >+ out.write(CONTENT_TYPE_BYTES); > >+ out.write(HttpConstants.getAsciiBytes(contentType)); > >+ String charSet = getCharSet(); > >+ if (charSet != null) { > >+ out.write(CHARSET_BYTES); > >+ out.write(HttpConstants.getAsciiBytes(charSet)); > >+ } > >+ } > > } > >- > >+ > > /** > >- * Return the length of the header > >+ * Write the content transfer encoding header to the specified > >+ * output stream > > * > >- * @return long The length. > >- * @throws IOException If an IO problem occurs > >+ * @param out The output stream > >+ * @throws IOException If an IO problem occurs. > > */ > >- protected int lengthOfHeader() throws IOException { > >- LOG.trace("enter lengthOfHeader()"); > >- ByteArrayOutputStream out = new ByteArrayOutputStream(); > >- sendHeader(out); > >- return (out.size()); > >+ > >+ protected void sendTransferEncodingHeader(OutputStream out) throws >IOException { > >+ LOG.trace("enter sendTransferEncodingHeader(OutputStream out)"); > >+ String transferEncoding = getTransferEncoding(); > >+ if (transferEncoding != null) { > >+ out.write(CRLF_BYTES); > >+ out.write(CONTENT_TRANSFER_ENCODING_BYTES); > >+ out.write(HttpConstants.getAsciiBytes(transferEncoding)); > >+ } > > } > >- > >- > >+ > > /** > > * Write the end of the header to the output stream > > * @param out The output stream > >@@ -211,20 +257,6 @@ > > } > > > > /** > >- * Return the length of the end of header > >- * > >- * @return long The length. > >- * @throws IOException If an IO problem occurs > >- */ > >- protected int lengthOfEndOfHeader() throws IOException { > >- LOG.trace("enter lengthOfEndOfHeader()"); > >- ByteArrayOutputStream out = new ByteArrayOutputStream(); > >- sendEndOfHeader(out); > >- return out.size(); > >- } > >- > >- > >- /** > > * Write the data to the specified output stream > > * @param out The output stream > > * @throws IOException If an IO problem occurs. > >@@ -249,51 +281,60 @@ > > out.write(CRLF_BYTES); > > } > > > >- /** > >- * Return the length of the end data > >- * > >- * @return long The length. > >- * @throws IOException If an IO problem occurs > >- */ > >- protected int lengthOfEnd() throws IOException { > >- LOG.trace("enter lengthOfEnd()"); > >- ByteArrayOutputStream out = new ByteArrayOutputStream(); > >- sendEnd(out); > >- return out.size(); > >- } > >- > >- /* The following 2 methods don't need to be final, but they DO need > >- * to be overridden as a pair, and the only way to make sure of that > >- * is to make sure they AREN'T overridden. > >- */ > >- > >+/* > >+ protected static void byteArrayToWire(final byte[] rawdata, final String >charset) > >+ throws IOException { > >+ Reader reader = null; > >+ try { > >+ reader = new InputStreamReader(new ByteArrayInputStream(rawdata), >charset); > >+ } catch (UnsupportedEncodingException e) { > >+ reader = new InputStreamReader(new ByteArrayInputStream(rawdata)); > >+ } > >+ BufferedReader in = new BufferedReader(reader); > >+ String line; > >+ while( (line = in.readLine()) != null ) { > >+ WIRE_LOG.debug(">> \"" + line + "\" [\\r\\n]"); > >+ } > >+ } > >+ */ > > /** > > * Write all the data to the output stream. > >+ * If you override this method make sure to override > >+ * #length() as well > >+ * > > * @param out The output stream > > * @throws IOException If an IO problem occurs. > > */ > >- public final void send(OutputStream out) throws IOException { > >+ public void send(OutputStream out) throws IOException { > > LOG.trace("enter send(OutputStream out)"); > > sendStart(out); > >- sendHeader(out); > >+ sendDispositionHeader(out); > >+ sendContentTypeHeader(out); > >+ sendTransferEncodingHeader(out); > > sendEndOfHeader(out); > > sendData(out); > > sendEnd(out); > > } > >- > >+ > >+ > > /** > > * Return the full length of all the data. > >+ * If you override this method make sure to override > >+ * #send(OutputStream) as well > > * > > * @return long The length. > > * @throws IOException If an IO problem occurs > > */ > >- public final long length() throws IOException { > >+ public long length() throws IOException { > > LOG.trace("enter length()"); > >- return lengthOfStart() > >- + lengthOfHeader() > >- + lengthOfEndOfHeader() > >- + lengthOfData() > >- + lengthOfEnd(); > >+ ByteArrayOutputStream overhead = new ByteArrayOutputStream(); > >+ sendStart(overhead); > >+ sendDispositionHeader(overhead); > >+ sendContentTypeHeader(overhead); > >+ sendTransferEncodingHeader(overhead); > >+ sendEndOfHeader(overhead); > >+ sendEnd(overhead); > >+ return overhead.size() + lengthOfData(); > > } > > > > /** > >@@ -304,4 +345,55 @@ > > public String toString() { > > return this.getName(); > > } > >+ > >+ > >+ /** > >+ * Write all parts and the last boundary to the specified output stream > >+ * > >+ * @param out The output stream > >+ * @param parts The array of parts to be sent > >+ * > >+ * @throws IOException If an IO problem occurs. > >+ */ > >+ public static void sendParts(OutputStream out, final Part[] parts) > >+ throws IOException { > >+ LOG.trace("enter sendParts(OutputStream out, Parts[])"); > >+ if (parts == null) { > >+ throw new IllegalArgumentException("Parts may not be null"); > >+ } > >+ if (WIRE_LOG.isDebugEnabled()) { > >+ out = new WireLogOutputStream(out, "US-ACSII"); > >+ } > >+ for (int i = 0; i < parts.length; i++) { > >+ parts[i].send(out); > >+ } > >+ out.write(EXTRA_BYTES); > >+ out.write(BOUNDARY_BYTES); > >+ out.write(EXTRA_BYTES); > >+ out.write(CRLF_BYTES); > >+ } > >+ > >+ /** > >+ * Return the total sum of all parts and that of the last boundary > >+ * > >+ * @param parts The array of parts > >+ * > >+ * @throws IOException If an IO problem occurs. > >+ */ > >+ public static long getLengthOfParts(final Part[] parts) > >+ throws IOException { > >+ LOG.trace("getLengthOfParts(Parts[])"); > >+ if (parts == null) { > >+ throw new IllegalArgumentException("Parts may not be null"); > >+ } > >+ long total = 0; > >+ for (int i = 0; i < parts.length; i++) { > >+ total += parts[i].length(); > >+ } > >+ total += EXTRA_BYTES.length; > >+ total += BOUNDARY_BYTES.length; > >+ total += EXTRA_BYTES.length; > >+ total += CRLF_BYTES.length; > >+ return total; > >+ } > > } > >Index: src/java/org/apache/commons/httpclient/methods/multipart/StringPart.java > >=================================================================== > >RCS file: >/home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/multipart/StringPart.java,v > >retrieving revision 1.5 > >diff -u -r1.5 StringPart.java > >--- src/java/org/apache/commons/httpclient/methods/multipart/StringPart.java 28 Jan >2003 22:25:31 -0000 1.5 > >+++ src/java/org/apache/commons/httpclient/methods/multipart/StringPart.java 10 Feb >2003 22:02:17 -0000 > >@@ -66,6 +66,8 @@ > > import java.io.OutputStream; > > import java.io.IOException; > > import org.apache.commons.httpclient.HttpConstants; > >+import org.apache.commons.logging.Log; > >+import org.apache.commons.logging.LogFactory; > > > > /** > > * Simple string parameter for a multipart post > >@@ -73,26 +75,69 @@ > > * @author <a href="mailto:[EMAIL PROTECTED]">Matthew Albright</a> > > * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Dever</a> > > * @author <a href="mailto:[EMAIL PROTECTED]">Mike Bowler</a> > >+ * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Kalnichevski</a> > > * > > * @since 2.0 > > */ > > public class StringPart extends Part { > > > >+ /** Log object for this class. */ > >+ private static final Log LOG = LogFactory.getLog(StringPart.class); > >+ > >+ /** Default content encoding of string parameters. */ > >+ public static final String DEFAULT_CONTENT_TYPE = "text/plain"; > >+ > >+ /** Default charset of string parameters*/ > >+ public static final String DEFAULT_CHARSET = "US-ASCII"; > >+ > >+ /** Default transfer encoding of string parameters*/ > >+ public static final String DEFAULT_TRANSFER_ENCODING = "8bit"; > >+ > > /** Name of this StringPart. */ > > private String name; > > > > /** Contents of this StringPart. */ > >- private String value; > >+ private byte[] content; > >+ > >+ /** Charset of this StringPart. */ > >+ private String charset; > > > > /** > > * Constructor. > > * > > * @param name The name of the part > > * @param value the string to post > >+ * @param charset the charset to be used to encode the string > > */ > >- public StringPart(String name, String value) { > >+ public StringPart(String name, String value, String charset) { > >+ LOG.trace("enter StringPart(String, String, String)"); > >+ if (name == null) { > >+ throw new IllegalArgumentException("Name may not be null"); > >+ } > > this.name = name; > >- this.value = value; > >+ if (charset != null) { > >+ this.charset = charset; > >+ } else { > >+ this.charset = DEFAULT_CHARSET; > >+ } > >+ if (value == null) { > >+ throw new IllegalArgumentException("Value may not be null"); > >+ } > >+ if (value.indexOf(0) != -1) { > >+ // See RFC 2048, 2.8. "8bit Data" > >+ throw new IllegalArgumentException("NULs may not be present in string >parts"); > >+ } > >+ this.content = HttpConstants.getContentBytes(value, this.charset); > >+ } > >+ > >+ /** > >+ * Constructor. > >+ * > >+ * @param name The name of the part > >+ * @param value the string to post > >+ */ > >+ public StringPart(String name, String value) { > >+ this(name, value, null); > > } > > > > /** > >@@ -102,15 +147,35 @@ > > public String getName() { > > return name; > > } > >- > >+ > > /** > >- * Write the data to the specified output stream > >- * @param out The output stream. > >- * @throws IOException If an IO problem occurs > >- * @see >org.apache.commons.httpclient.methods.multipart.Part#sendData(OutputStream) > >+ * Return the content type of this part. > >+ * @return String The name. > >+ */ > >+ public String getContentType() { > >+ return DEFAULT_CONTENT_TYPE; > >+ } > >+ > >+ /** > >+ * Return the character encoding of this part. > >+ * @return String The name. > > */ > >+ public String getCharSet() { > >+ return this.charset; > >+ } > >+ > >+ /** > >+ * Return the transfer encoding of this part. > >+ * @return String The name. > >+ */ > >+ > >+ public String getTransferEncoding() { > >+ return DEFAULT_TRANSFER_ENCODING; > >+ } > >+ > > protected void sendData(OutputStream out) throws IOException { > >- out.write(HttpConstants.getBytes(value)); > >+ LOG.trace("enter sendData(OutputStream)"); > >+ out.write(this.content); > > } > > > > /** > >@@ -120,6 +185,7 @@ > > * @see org.apache.commons.httpclient.methods.multipart.Part#lengthOfData() > > */ > > protected long lengthOfData() throws IOException { > >- return HttpConstants.getBytes(value).length; > >+ LOG.trace("enter lengthOfData()"); > >+ return this.content.length; > > } > > } > >Index: src/java/org/apache/commons/httpclient/util/Wire.java > >=================================================================== > >RCS file: src/java/org/apache/commons/httpclient/util/Wire.java > >diff -N src/java/org/apache/commons/httpclient/util/Wire.java > >--- /dev/null 1 Jan 1970 00:00:00 -0000 > >+++ src/java/org/apache/commons/httpclient/util/Wire.java 10 Feb 2003 22:02:14 >-0000 > >@@ -0,0 +1,167 @@ > >+/* > >+ * ==================================================================== > >+ * > >+ * The Apache Software License, Version 1.1 > >+ * > >+ * Copyright (c) 1999-2003 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", "Commons", 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.util; > >+ > >+import java.io.IOException; > >+import java.io.InputStream; > >+import java.io.ByteArrayInputStream; > >+import java.io.Reader; > >+import java.io.InputStreamReader; > >+import java.io.BufferedReader; > >+import java.io.UnsupportedEncodingException; > >+import org.apache.commons.logging.Log; > >+import org.apache.commons.logging.LogFactory; > >+ > >+/** > >+ * Logs data to the wire LOG. > >+ * > >+ * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Kalnichevski</a> > >+ * > >+ * @since 2.0beta1 > >+ */ > >+ > >+public class Wire { > >+ > >+ /** Log for any wire messages. */ > >+ private static final Log WIRE_LOG = LogFactory.getLog("httpclient.wire"); > >+ > >+ private static void wire(String header, InputStream instream, String charset) > >+ throws IOException { > >+ if (charset == null) { > >+ charset = "US-ASCII"; > >+ } > >+ Reader reader = null; > >+ try { > >+ reader = new InputStreamReader(instream, charset); > >+ } catch (UnsupportedEncodingException e) { > >+ reader = new InputStreamReader(instream); > >+ } > >+ StringBuffer buffer = new StringBuffer(); > >+ int ch; > >+ while ((ch = reader.read()) != -1) { > >+ if (ch == 13) { > >+ buffer.append("[\\r]"); > >+ } else if (ch == 10){ > >+ buffer.append("[\\n]\""); > >+ buffer.insert(0, "\""); > >+ buffer.insert(0, header); > >+ WIRE_LOG.debug(buffer.toString()); > >+ buffer.setLength(0); > >+ } else if ((ch < 32) || (ch > 127)) { > >+ buffer.append("[0x"); > >+ buffer.append(Integer.toHexString(ch)); > >+ buffer.append("]"); > >+ } else { > >+ buffer.append((char)ch); > >+ } > >+ } > >+ if (buffer.length() > 0) { > >+ buffer.append("\""); > >+ buffer.insert(0, "\""); > >+ buffer.insert(0, header); > >+ WIRE_LOG.debug(buffer.toString()); > >+ } > >+ } > >+ > >+ > >+ public static final boolean enabled() { > >+ return WIRE_LOG.isDebugEnabled(); > >+ } > >+ > >+ public static final void output(InputStream instream, String charset) > >+ throws IOException { > >+ wire(">> ", instream, charset); > >+ } > >+ > >+ public static final void input(InputStream instream, String charset) > >+ throws IOException { > >+ wire("<< ", instream, charset); > >+ } > >+ > >+ public static final void output(byte[] b, int off, int len, String charset) > >+ throws IOException { > >+ wire(">> ", new ByteArrayInputStream(b, off, len), charset); > >+ } > >+ > >+ public static final void input(byte[] b, int off, int len, String charset) > >+ throws IOException { > >+ wire("<< ", new ByteArrayInputStream(b, off, len), charset); > >+ } > >+ > >+ public static final void output(byte[] b, String charset) > >+ throws IOException { > >+ wire(">> ", new ByteArrayInputStream(b), charset); > >+ } > >+ > >+ public static final void input(byte[] b, String charset) > >+ throws IOException { > >+ wire("<< ", new ByteArrayInputStream(b), charset); > >+ } > >+ > >+ public static final void output(int b, String charset) > >+ throws IOException { > >+ output(new byte[] {(byte)b}, charset); > >+ } > >+ > >+ public static final void input(int b, String charset) > >+ throws IOException { > >+ input(new byte[] {(byte)b}, charset); > >+ } > >+} > >Index: src/test/org/apache/commons/httpclient/TestWebapp.java > >=================================================================== > >RCS file: >/home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestWebapp.java,v > >retrieving revision 1.6 > >diff -u -r1.6 TestWebapp.java > >--- src/test/org/apache/commons/httpclient/TestWebapp.java 1 Feb 2003 16:10:48 >-0000 1.6 > >+++ src/test/org/apache/commons/httpclient/TestWebapp.java 10 Feb 2003 22:02:05 >-0000 > >@@ -1,5 +1,5 @@ > > /* > >- * $Header: >/home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestWebapp.java,v > 1.6 2003/02/01 16:10:48 olegk Exp $ > >+ * $Header: >/home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestWebapp.java,v > 1.6 2003/02/01 16:10:48 olegk Exp $ > > * $Revision: 1.6 $ > > * $Date: 2003/02/01 16:10:48 $ > > * ==================================================================== > >@@ -100,6 +100,7 @@ > > suite.addTest(TestWebappBasicAuth.suite()); > > suite.addTest(TestWebappCookie.suite()); > > suite.addTest(TestWebappPostMethod.suite()); > >+ suite.addTest(TestWebappMultiPostMethod.suite()); > > suite.addTest(TestWebappNoncompliant.suite()); > > return suite; > > } > >Index: src/test/org/apache/commons/httpclient/TestWebappMultiPostMethod.java > >=================================================================== > >RCS file: src/test/org/apache/commons/httpclient/TestWebappMultiPostMethod.java > >diff -N src/test/org/apache/commons/httpclient/TestWebappMultiPostMethod.java > >--- /dev/null 1 Jan 1970 00:00:00 -0000 > >+++ src/test/org/apache/commons/httpclient/TestWebappMultiPostMethod.java 10 Feb >2003 22:02:06 -0000 > >@@ -0,0 +1,146 @@ > >+/* > >+ * $Header: >/home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestWebappPostMethod.java,v > 1.2 2003/02/03 21:21:19 olegk Exp $ > >+ * $Revision: 1.2 $ > >+ * $Date: 2003/02/03 21:21:19 $ > >+ * > >+ * ==================================================================== > >+ * > >+ * The Apache Software License, Version 1.1 > >+ * > >+ * Copyright (c) 2003 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", "Commons", 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 junit.framework.*; > >+import org.apache.commons.httpclient.methods.*; > >+import org.apache.commons.httpclient.methods.multipart.*; > >+import java.io.*; > >+ > >+/** > >+ * Webapp tests specific to the MultiPostMethod. > >+ * > >+ * @author <a href="[EMAIL PROTECTED]">Oleg Kalnichevski</a> > >+ */ > >+public class TestWebappMultiPostMethod extends TestWebappBase { > >+ > >+ HttpClient httpClient; > >+ final static String paramsUrl = "http://" + host + ":" + port > >+ + "/" + context + "/params"; > >+ final static String bodyUrl = "http://" + host + ":" + port > >+ + "/" + context + "/body"; > >+ > >+ public TestWebappMultiPostMethod(String testName) { > >+ super(testName); > >+ } > >+ > >+ public static Test suite() { > >+ TestSuite suite = new TestSuite(TestWebappMultiPostMethod.class); > >+ return suite; > >+ } > >+ > >+ public static void main(String args[]) { > >+ String[] testCaseName = { TestWebappMultiPostMethod.class.getName() }; > >+ junit.textui.TestRunner.main(testCaseName); > >+ } > >+ > >+ public void setUp() { > >+ httpClient = new HttpClient(); > >+ } > >+ > >+ // ------------------------------------------------------------------ Tests > >+ > >+ /** > >+ * Test that the body consisting of a string part can be posted. > >+ */ > >+ > >+ public void testPostStringPart() throws Exception { > >+ MultipartPostMethod method = new MultipartPostMethod(bodyUrl); > >+ method.addPart(new StringPart("param", "Hello", "ISO-8859-1")); > >+ > >+ httpClient.executeMethod(method); > >+ > >+ assertEquals(200,method.getStatusCode()); > >+ String body = method.getResponseBodyAsString(); > >+ assertTrue(body.indexOf("Content-Disposition: form-data; name=\"param\"") >>= 0); > >+ assertTrue(body.indexOf("Content-Type: text/plain; charset=ISO-8859-1") >= >0); > >+ assertTrue(body.indexOf("Content-Transfer-Encoding: 8bit") >= 0); > >+ assertTrue(body.indexOf("Hello") >= 0); > >+ } > >+ > >+ > >+ /** > >+ * Test that the body consisting of a file part can be posted. > >+ */ > >+ public void testPostFilePart() throws Exception { > >+ MultipartPostMethod method = new MultipartPostMethod(bodyUrl); > >+ byte[] content = new byte[] {'H', 'e', 'l', 'l', 'o' }; > >+ method.addPart( > >+ new FilePart( > >+ "param1", > >+ new ByteArrayPartSource("filename.txt", content), > >+ "text/plain", > >+ "ISO-8859-1")); > >+ > >+ httpClient.executeMethod(method); > >+ > >+ assertEquals(200,method.getStatusCode()); > >+ String body = method.getResponseBodyAsString(); > >+ assertTrue(body.indexOf("Content-Disposition: form-data; name=\"param1\"; >filename=\"filename.txt\"") >= 0); > >+ assertTrue(body.indexOf("Content-Type: text/plain; charset=ISO-8859-1") >= >0); > >+ assertTrue(body.indexOf("Content-Transfer-Encoding: binary") >= 0); > >+ assertTrue(body.indexOf("Hello") >= 0); > >+ } > >+} > >+ > > > > > > > >------------------------------------------------------------------------ > > > >--------------------------------------------------------------------- > >To unsubscribe, e-mail: [EMAIL PROTECTED] > >For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]