You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-dev@xml.apache.org by Pavel Ausianik <Pa...@epam.com> on 2002/11/12 16:53:59 UTC
RE: cvs commit: xml-soap/java/src/org/apache/soap/transport/http
SOAPHTTPConnection.java
Scott,
i don't know if this makes sence, but logic little bit strange, in case
contentLength=0. See buffer has been created, but as I can see it is not
used anymore since the following block finishes at the end. Should be there
condition to go inside and read from buffer?
bytes = new byte[contentLength >= 0 ? contentLength : 4096];
if (contentLength != 0) {
Pavel
> -----Original Message-----
> From: snichol@apache.org [mailto:snichol@apache.org]
> Sent: Tuesday, November 12, 2002 4:16 PM
> To: xml-soap-cvs@apache.org
> Subject: cvs commit: xml-soap/java/src/org/apache/soap/transport/http
> SOAPHTTPConnection.java
>
>
> snichol 2002/11/12 06:15:38
>
> Modified: java/src/org/apache/soap/util/net HTTPUtils.java
> java/src/org/apache/soap/transport
> TransportMessage.java
> java/src/org/apache/soap/transport/http
> SOAPHTTPConnection.java
> Log:
> Reduce the number of times a response is copied in part or in whole.
> Improve error reporting during response parsing.
> Support services that shutdown the write half of the socket
> rather than
> provide a Content-Length header.
> Add getEnvelope to SOAPHTTPConnection. (The method will
> also be added
> to SOAPTransport soon.)
>
> Revision Changes Path
> 1.36 +104 -82
> xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java
>
> Index: HTTPUtils.java
> ===================================================================
> RCS file:
> /home/cvs/xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java,v
> retrieving revision 1.35
> retrieving revision 1.36
> diff -u -r1.35 -r1.36
> --- HTTPUtils.java 18 Oct 2002 20:30:54 -0000 1.35
> +++ HTTPUtils.java 12 Nov 2002 14:15:38 -0000 1.36
> @@ -57,21 +57,30 @@
>
> package org.apache.soap.util.net;
>
> -import java.io.*;
> -import java.lang.reflect.*;
> -import java.net.*;
> -import java.util.*;
> -
> -import javax.mail.*;
> -import javax.mail.internet.*;
> -import javax.activation.*;
> +import java.io.BufferedInputStream;
> +import java.io.BufferedOutputStream;
> +import java.io.BufferedReader;
> +import java.io.InputStream;
> +import java.io.IOException;
> +import java.io.OutputStream;
> +import java.io.UnsupportedEncodingException;
> +import java.lang.reflect.InvocationTargetException;
> +import java.lang.reflect.Method;
> +import java.net.HttpURLConnection;
> +import java.net.Socket;
> +import java.net.URL;
> +import java.util.Enumeration;
> +import java.util.Hashtable;
> +import java.util.StringTokenizer;
>
> -import org.apache.soap.*;
> +import javax.mail.MessagingException;
> +
> +import org.apache.soap.Constants;
> +import org.apache.soap.SOAPException;
> import org.apache.soap.encoding.soapenc.Base64;
> -import org.apache.soap.rpc.*;
> -import org.apache.soap.transport.*;
> +import org.apache.soap.rpc.SOAPContext;
> +import org.apache.soap.transport.TransportMessage;
> import org.apache.soap.util.MutableBoolean;
> -import org.apache.soap.util.mime.*;
>
> /**
> * A bunch of utility stuff for doing HTTP things.
> @@ -91,6 +100,7 @@
> private static final String HTTP_VERSION = "1.0";
> private static final int HTTP_DEFAULT_PORT = 80;
> private static final int HTTPS_DEFAULT_PORT = 443;
> + private static final String ISO_8859_1 = "8859_1";
>
> public static final int DEFAULT_OUTPUT_BUFFER_SIZE =
> 8 * 1024;
>
> @@ -100,7 +110,7 @@
> public static String encodeAuth(String userName, String password)
> throws SOAPException {
> try {
> - return Base64.encode((userName + ":" +
> password).getBytes("8859_1"));
> + return Base64.encode((userName + ":" +
> password).getBytes(ISO_8859_1));
> } catch (UnsupportedEncodingException e) {
> throw new SOAPException
> (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> }
> @@ -482,65 +492,93 @@
> bOutStream.flush();
>
> BufferedInputStream bInStream = new
> BufferedInputStream(inStream);
> + byte[] linebuf = new byte[1024];
> + int count = 0;
> + int b;
> +
> /* Read the response status line. */
> + String versionString = null;
> int statusCode = 0;
> String statusString = null;
> - StringBuffer linebuf = new StringBuffer(128);
> - int b = 0;
> - while (b != '\n' && b != -1) {
> - b = bInStream.read();
> - if (b != '\n' && b != '\r' && b != -1)
> - linebuf.append((char)b);
> - }
> - String line = linebuf.toString();
> +
> try {
> - StringTokenizer st = new StringTokenizer(line);
> - st.nextToken(); // ignore version part
> - statusCode = Integer.parseInt (st.nextToken());
> - StringBuffer sb = new StringBuffer(128);
> - while (st.hasMoreTokens()) {
> - sb.append (st.nextToken());
> - if (st.hasMoreTokens()) {
> - sb.append(" ");
> + int versionEnd = -1;
> + int codeStart = -1;
> + int codeEnd = -1;
> + int stringStart = -1;
> +
> + for (count = 0, b = bInStream.read(); b != '\n'
> && b != -1; b = bInStream.read()) {
> + if (b != '\r') {
> + if (b == ' ') {
> + if (versionEnd == -1) {
> + versionEnd = count;
> + } else if (codeStart != -1 &&
> codeEnd == -1) {
> + codeEnd = count;
> + }
> + } else {
> + if (versionEnd != -1 && codeStart == -1) {
> + codeStart = count;
> + } else if (codeEnd != -1 &&
> stringStart == -1) {
> + stringStart = count;
> + }
> + }
> + if (count >= linebuf.length) {
> + byte[] newbuf = new byte[linebuf.length * 2];
> + System.arraycopy(linebuf, 0, newbuf,
> 0, linebuf.length);
> + linebuf = newbuf;
> + }
> + linebuf[count++] = (byte) b;
> }
> }
> - statusString = sb.toString();
> - }
> - catch (Exception e) {
> + if (b == -1)
> + throw new Exception("Reached end of stream
> while reading HTTP response status");
> + versionString = new String(linebuf, 0,
> versionEnd, ISO_8859_1);
> + statusCode = Integer.parseInt(new
> String(linebuf, codeStart, codeEnd - codeStart, ISO_8859_1));
> + statusString = new String(linebuf, stringStart,
> count - stringStart, ISO_8859_1);
> + } catch (Exception e) {
> throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> - "Error parsing HTTP status line \"" + line +
> "\": " + e, e);
> + "Error parsing HTTP status line \"" + new
> String(linebuf, 0, count, ISO_8859_1) + "\": " + e, e);
> }
>
> - /* Read the entire response (following the status line)
> - * into a byte array. */
> - ByteArrayDataSource ds = new ByteArrayDataSource(bInStream,
> - Constants.HEADERVAL_DEFAULT_CHARSET);
> -
> - /* Extract the headers, content type and content length. */
> - byte[] bytes = ds.toByteArray();
> + /* Read the HTTP headers. */
> Hashtable respHeaders = new Hashtable();
> int respContentLength = -1;
> String respContentType = null;
>
> - int nameStart = 0;
> - int nameEnd = 0;
> - int valStart = 0;
> - boolean parsingName = true;
> - int offset;
> -
> - for (offset = 0; offset < bytes.length; offset++) {
> - if (bytes[offset] == '\n') {
> - if (nameStart >= nameEnd)
> + try {
> + // Read all headers
> + for (;;) {
> + // Read and parse one header
> + int nameEnd = -1;
> + int valStart = -1;
> + for (count = 0, b = bInStream.read(); b !=
> '\n' && b != -1; b = bInStream.read()) {
> + if (b != '\r') {
> + if (nameEnd == -1 && b == ':') {
> + nameEnd = count;
> + } else if (nameEnd != -1 && valStart
> == -1 && b != ' ' & b != '\t') {
> + valStart = count;
> + }
> + if (count >= linebuf.length) {
> + byte[] newbuf = new
> byte[linebuf.length * 2];
> + System.arraycopy(linebuf, 0,
> newbuf, 0, linebuf.length);
> + linebuf = newbuf;
> + }
> + linebuf[count++] = (byte) b;
> + }
> + }
> + if (b == -1)
> + throw new Exception("Reached end of
> stream while reading HTTP response header");
> + if (count == 0) // Read the header/entity separator
> break;
> - String name = new String(bytes, nameStart,
> nameEnd-nameStart+1);
> -
> - // Remove trailing ; to prevent ContextType
> from throwing exception
> - int valueLen = offset - valStart -1;
> + if (nameEnd == -1 || valStart == -1)
> + throw new Exception("Incorrectly formed
> HTTP response header");
>
> - if (valueLen > 0 && bytes[offset-1] == ';')
> - valueLen--;
> + String name = new String(linebuf, 0,
> nameEnd, ISO_8859_1);
> + // Remove trailing ; to prevent ContentType
> from throwing exception
> + if (linebuf[count - 1] == ';')
> + --count;
> + String value = new String(linebuf, valStart,
> count - valStart, ISO_8859_1);
>
> - String value = new String(bytes, valStart, valueLen);
> if
> (name.equalsIgnoreCase(Constants.HEADER_CONTENT_LENGTH))
> respContentLength = Integer.parseInt(value);
> else if
> (name.equalsIgnoreCase(Constants.HEADER_CONTENT_TYPE))
> @@ -556,27 +594,11 @@
> }
> }
> }
> - parsingName = true;
> - nameStart = offset+1;
> }
> - else if (bytes[offset] != '\r') {
> - if (parsingName) {
> - if (bytes[offset] == ':') {
> - parsingName = false;
> - nameEnd = offset - 1;
> - if ((offset != bytes.length-1) &&
> - bytes[offset+1] == ' ')
> - offset++;
> - valStart = offset+1;
> - }
> - }
> - }
> - } // End of for
> -
> - InputStream is = ds.getInputStream();
> - is.skip(offset + 1);
> - if (respContentLength < 0)
> - respContentLength = ds.getSize() - offset - 1;
> + } catch (Exception e) {
> + throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> + "Error parsing HTTP header line \"" + new
> String(linebuf, 0, count, ISO_8859_1) + "\": " + e, e);
> + }
>
> /* Handle redirect here */
> if (statusCode >= HttpURLConnection.HTTP_MULT_CHOICE &&
> @@ -595,11 +617,6 @@
> }
> }
>
> - /* If required, capture a copy of the response. */
> - if (responseCopy != null) {
> -
> responseCopy.append(line).append("\r\n").append(new
> String(bytes)); /* May get junk due to actual encoding */
> - }
> -
> // TODO: process differently depending on statusCode
> and respContentLength
> // (TransportMessage does not even get statusCode)
> // e.g. statusCode 401 is Unauthorized
> @@ -612,13 +629,18 @@
> // Create response SOAPContext.
> ctx = new SOAPContext();
> // Read content.
> - response = new TransportMessage(is, respContentLength,
> + response = new TransportMessage(bInStream,
> respContentLength,
> respContentType,
> ctx, respHeaders);
> // Extract envelope and SOAPContext
> response.read();
> } catch (MessagingException me) {
> throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> "Error parsing response:
> " + me, me);
> + }
> +
> + /* If required, capture a copy of the response. */
> + if (responseCopy != null) {
> + responseCopy.append(new
> String(response.getBytes())); /* May get junk due to actual
> encoding */
> }
>
> /* All done here! */
>
>
>
> 1.17 +51 -37
> xml-soap/java/src/org/apache/soap/transport/TransportMessage.java
>
> Index: TransportMessage.java
> ===================================================================
> RCS file:
> /home/cvs/xml-soap/java/src/org/apache/soap/transport/Transpor
tMessage.java,v
> retrieving revision 1.16
> retrieving revision 1.17
> diff -u -r1.16 -r1.17
> --- TransportMessage.java 6 Sep 2002 17:02:58 -0000 1.16
> +++ TransportMessage.java 12 Nov 2002 14:15:38 -0000 1.17
> @@ -128,25 +128,36 @@
> this.ctx = ctx;
> this.contentType = contentType;
>
> - if (contentLength < 0)
> - throw new SOAPException (Constants.FAULT_CODE_PROTOCOL,
> - "Content length must
> be specified.");
> -
> - bytes = new byte[contentLength];
> - int offset = 0;
> - int bytesRead = 0;
> -
> - // We're done reading when we get all the content
> OR when the stream
> - // returns a -1.
> - while ((offset < contentLength) && (bytesRead >= 0)) {
> - bytesRead = is.read(bytes, offset,
> contentLength - offset);
> - offset += bytesRead;
> - }
> - if (offset < contentLength)
> - throw new SOAPException (Constants.FAULT_CODE_PROTOCOL,
> - "Premature end of stream. Data is
> truncated. Read "
> - + offset + " bytes successfully, expected "
> - + contentLength);
> + bytes = new byte[contentLength >= 0 ?
> contentLength : 4096];
> + if (contentLength != 0) {
> + int offset = 0;
> + int bytesRead = 0;
> +
> + // We're done reading when we get all the
> content OR when the stream
> + // returns a -1.
> + while ((contentLength < 0 || offset <
> contentLength) && (bytesRead >= 0)) {
> + bytesRead = is.read(bytes, offset,
> bytes.length - offset);
> + offset += bytesRead;
> + if (contentLength < 0 && offset >= bytes.length) {
> + byte[] newbuf = new byte[bytes.length * 2];
> + System.arraycopy(bytes, 0, newbuf, 0,
> bytes.length);
> + bytes = newbuf;
> + }
> + }
> +
> + if (contentLength < 0) {
> + if (offset < bytes.length) {
> + byte[] newbuf = new byte[offset];
> + System.arraycopy(bytes, 0, newbuf, 0, offset);
> + bytes = newbuf;
> + }
> + } else if (offset < contentLength) {
> + throw new SOAPException
> (Constants.FAULT_CODE_PROTOCOL,
> + "Premature end of stream. Data
> is truncated. Read "
> + + offset + " bytes
> successfully, expected "
> + + contentLength);
> + }
> + }
> }
>
> /**
> @@ -284,7 +295,7 @@
> }
>
> // If the root part is text, extract it as a String.
> - // Note that we could use JAF's help to do this
> (see getEnvelope())
> + // Note that we could use JAF's help to do this
> (see save())
> // but implementing it ourselves is safer and faster.
> if (rootContentType.match("text/*")) {
> String charset =
> rootContentType.getParameter("charset");
> @@ -323,9 +334,11 @@
> */
> public void save()
> throws MessagingException, IOException {
> - /* If an envelope was provided as a string, set it
> as the root part.
> - * Otherwise, assume that the SOAPContext already
> has a root part.
> + /*
> + * If an envelope was provided as a string, set it
> as the root part.
> * If there was already a root part, preserve its
> content-type.
> + * Otherwise, assume that the SOAPContext already
> has a root part,
> + * and try to use it as the envelope.
> */
> String rootContentType = null;
> if (ctx.isRootPartSet()) {
> @@ -339,8 +352,18 @@
> }
> if (rootContentType == null)
> rootContentType =
> Constants.HEADERVAL_CONTENT_TYPE_UTF8;
> - if (getEnvelope() != null)
> + if (getEnvelope() != null) {
> ctx.setRootPart(envelope, rootContentType);
> + } else {
> + MimeBodyPart rootPart = ctx.getRootPart();
> + if (rootPart != null) {
> + if (rootPart.isMimeType("text/*")) {
> + ByteArrayDataSource ds = new
> ByteArrayDataSource(
> + rootPart.getInputStream(),
> rootPart.getContentType());
> + envelope = ds.getText();
> + }
> + }
> + }
>
> // Print the whole response to a byte array.
> ByteArrayOutputStream payload =
> @@ -428,20 +451,9 @@
> }
>
> /**
> - * Get SOAP Envelope/root part as a String.
> - * This method will extract the root part from the
> SOAPContext as a String
> - * if there is no SOAP Envelope.
> + * Get SOAP Envelope as a String.
> */
> - public String getEnvelope() throws MessagingException,
> IOException {
> - if (envelope == null) {
> - MimeBodyPart rootPart = ctx.getRootPart();
> - if (rootPart != null)
> - if (rootPart.isMimeType("text/*")) {
> - ByteArrayDataSource ds = new
> ByteArrayDataSource(
> - rootPart.getInputStream(),
> rootPart.getContentType());
> - envelope = ds.getText();
> - }
> - }
> + public String getEnvelope() {
> return envelope;
> }
>
> @@ -449,7 +461,7 @@
> * Get SOAP Envelope/root part as a Reader. Returns
> null if the root part
> * is not text.
> */
> - public Reader getEnvelopeReader() throws
> MessagingException, IOException {
> + public Reader getEnvelopeReader() {
> if (getEnvelope() == null)
> return null;
> else
> @@ -530,6 +542,8 @@
>
> /**
> * Set the byte array of the response.
> + *
> + * @deprecated After 2.3.1
> */
> public void readFully(InputStream is) throws IOException {
> offset = 0;
>
>
>
> 1.29 +19 -16
> xml-soap/java/src/org/apache/soap/transport/http/SOAPHTTPConne
> ction.java
>
> Index: SOAPHTTPConnection.java
> ===================================================================
> RCS file:
> /home/cvs/xml-soap/java/src/org/apache/soap/transport/http/SOA
PHTTPConnection.java,v
> retrieving revision 1.28
> retrieving revision 1.29
> diff -u -r1.28 -r1.29
> --- SOAPHTTPConnection.java 16 Oct 2002 04:16:15 -0000 1.28
> +++ SOAPHTTPConnection.java 12 Nov 2002 14:15:38 -0000 1.29
> @@ -84,9 +84,7 @@
> * @author Arek Wnukowski (apache@wnuko.demon.co.uk)
> */
> public class SOAPHTTPConnection implements SOAPTransport {
> - private BufferedReader responseReader;
> - private Hashtable responseHeaders;
> - private SOAPContext responseSOAPContext;
> + private TransportMessage response;
>
> private String httpProxyHost;
> private int httpProxyPort = 80;
> @@ -369,7 +367,6 @@
> "Basic " +
> HTTPUtils.encodeAuth(proxyUserName, proxyPassword));
> }
>
> - TransportMessage response;
> try
> {
> TransportMessage msg = new
> TransportMessage(payload, ctx, headers);
> @@ -385,18 +382,12 @@
> throw new IOException ("Failed to encode mime
> multipart: " + uee);
> }
>
> - Reader envReader = response.getEnvelopeReader();
> - if (envReader != null)
> - responseReader = new BufferedReader(envReader);
> - else
> - responseReader = null;
> - responseSOAPContext = response.getSOAPContext();
> - responseHeaders = response.getHeaders();
> if (maintainSession) {
> // look for Set-Cookie2 and Set-Cookie headers and
> save them.
> // Only update my state iff the header is there ..
> otherwise
> // leave the current
> // Note: Header is case-insensitive
> + Hashtable responseHeaders = response.getHeaders();
> String hdr;
>
> hdr = HTTPUtils.getHeaderValue (responseHeaders,
> "Set-Cookie2");
> @@ -421,8 +412,6 @@
> }
> } catch (IllegalArgumentException e) {
> throw new SOAPException
> (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> - } catch (MessagingException e) {
> - throw new SOAPException
> (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> } catch (IOException e) {
> throw new SOAPException
> (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> }
> @@ -436,7 +425,21 @@
> * possible.
> */
> public BufferedReader receive () {
> - return responseReader;
> + if (response != null) {
> + Reader envReader = response.getEnvelopeReader();
> + if (envReader != null)
> + return new BufferedReader(envReader);
> + }
> + return null;
> + }
> +
> + /**
> + * Returns the SOAP envelope.
> + *
> + * @return The SOAP envelope.
> + */
> + public String getEnvelope() {
> + return response != null ? response.getEnvelope() : null;
> }
>
> /**
> @@ -445,7 +448,7 @@
> * @return a hashtable containing all the headers
> */
> public Hashtable getHeaders () {
> - return responseHeaders;
> + return response != null ? response.getHeaders() : null;
> }
>
> /**
> @@ -454,6 +457,6 @@
> * @return response SOAPContext
> */
> public SOAPContext getResponseSOAPContext () {
> - return responseSOAPContext;
> + return response != null ? response.getSOAPContext() : null;
> }
> }
>
>
>
>
> --
> To unsubscribe, e-mail: <ma...@xml.apache.org>
> For additional commands, e-mail: <ma...@xml.apache.org>
>
--
To unsubscribe, e-mail: <ma...@xml.apache.org>
For additional commands, e-mail: <ma...@xml.apache.org>
Re: cvs commit: xml-soap/java/src/org/apache/soap/transport/http
SOAPHTTPConnection.java
Posted by Scott Nichol <sn...@scottnichol.com>.
This is the case where the message has a Content-Length header
specifying 0 octets. I create the byte array of that length, but there
is no reason to read, since I want 0 bytes, which is what I already
have.
Scott Nichol
----- Original Message -----
From: "Pavel Ausianik" <Pa...@epam.com>
To: <so...@xml.apache.org>
Sent: Tuesday, November 12, 2002 10:53 AM
Subject: RE: cvs commit:
xml-soap/java/src/org/apache/soap/transport/http SOAPHTTPConnection.java
> Scott,
>
> i don't know if this makes sence, but logic little bit strange, in
case
> contentLength=0. See buffer has been created, but as I can see it is
not
> used anymore since the following block finishes at the end. Should be
there
> condition to go inside and read from buffer?
>
> bytes = new byte[contentLength >= 0 ? contentLength : 4096];
> if (contentLength != 0) {
>
> Pavel
>
> > -----Original Message-----
> > From: snichol@apache.org [mailto:snichol@apache.org]
> > Sent: Tuesday, November 12, 2002 4:16 PM
> > To: xml-soap-cvs@apache.org
> > Subject: cvs commit:
xml-soap/java/src/org/apache/soap/transport/http
> > SOAPHTTPConnection.java
> >
> >
> > snichol 2002/11/12 06:15:38
> >
> > Modified: java/src/org/apache/soap/util/net HTTPUtils.java
> > java/src/org/apache/soap/transport
> > TransportMessage.java
> > java/src/org/apache/soap/transport/http
> > SOAPHTTPConnection.java
> > Log:
> > Reduce the number of times a response is copied in part or in
whole.
> > Improve error reporting during response parsing.
> > Support services that shutdown the write half of the socket
> > rather than
> > provide a Content-Length header.
> > Add getEnvelope to SOAPHTTPConnection. (The method will
> > also be added
> > to SOAPTransport soon.)
> >
> > Revision Changes Path
> > 1.36 +104 -82
> > xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java
> >
> > Index: HTTPUtils.java
> >
===================================================================
> > RCS file:
> >
/home/cvs/xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java,v
> > retrieving revision 1.35
> > retrieving revision 1.36
> > diff -u -r1.35 -r1.36
> > --- HTTPUtils.java 18 Oct 2002 20:30:54 -0000 1.35
> > +++ HTTPUtils.java 12 Nov 2002 14:15:38 -0000 1.36
> > @@ -57,21 +57,30 @@
> >
> > package org.apache.soap.util.net;
> >
> > -import java.io.*;
> > -import java.lang.reflect.*;
> > -import java.net.*;
> > -import java.util.*;
> > -
> > -import javax.mail.*;
> > -import javax.mail.internet.*;
> > -import javax.activation.*;
> > +import java.io.BufferedInputStream;
> > +import java.io.BufferedOutputStream;
> > +import java.io.BufferedReader;
> > +import java.io.InputStream;
> > +import java.io.IOException;
> > +import java.io.OutputStream;
> > +import java.io.UnsupportedEncodingException;
> > +import java.lang.reflect.InvocationTargetException;
> > +import java.lang.reflect.Method;
> > +import java.net.HttpURLConnection;
> > +import java.net.Socket;
> > +import java.net.URL;
> > +import java.util.Enumeration;
> > +import java.util.Hashtable;
> > +import java.util.StringTokenizer;
> >
> > -import org.apache.soap.*;
> > +import javax.mail.MessagingException;
> > +
> > +import org.apache.soap.Constants;
> > +import org.apache.soap.SOAPException;
> > import org.apache.soap.encoding.soapenc.Base64;
> > -import org.apache.soap.rpc.*;
> > -import org.apache.soap.transport.*;
> > +import org.apache.soap.rpc.SOAPContext;
> > +import org.apache.soap.transport.TransportMessage;
> > import org.apache.soap.util.MutableBoolean;
> > -import org.apache.soap.util.mime.*;
> >
> > /**
> > * A bunch of utility stuff for doing HTTP things.
> > @@ -91,6 +100,7 @@
> > private static final String HTTP_VERSION = "1.0";
> > private static final int HTTP_DEFAULT_PORT = 80;
> > private static final int HTTPS_DEFAULT_PORT = 443;
> > + private static final String ISO_8859_1 = "8859_1";
> >
> > public static final int DEFAULT_OUTPUT_BUFFER_SIZE =
> > 8 * 1024;
> >
> > @@ -100,7 +110,7 @@
> > public static String encodeAuth(String userName, String
password)
> > throws SOAPException {
> > try {
> > - return Base64.encode((userName + ":" +
> > password).getBytes("8859_1"));
> > + return Base64.encode((userName + ":" +
> > password).getBytes(ISO_8859_1));
> > } catch (UnsupportedEncodingException e) {
> > throw new SOAPException
> > (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> > }
> > @@ -482,65 +492,93 @@
> > bOutStream.flush();
> >
> > BufferedInputStream bInStream = new
> > BufferedInputStream(inStream);
> > + byte[] linebuf = new byte[1024];
> > + int count = 0;
> > + int b;
> > +
> > /* Read the response status line. */
> > + String versionString = null;
> > int statusCode = 0;
> > String statusString = null;
> > - StringBuffer linebuf = new StringBuffer(128);
> > - int b = 0;
> > - while (b != '\n' && b != -1) {
> > - b = bInStream.read();
> > - if (b != '\n' && b != '\r' && b != -1)
> > - linebuf.append((char)b);
> > - }
> > - String line = linebuf.toString();
> > +
> > try {
> > - StringTokenizer st = new StringTokenizer(line);
> > - st.nextToken(); // ignore version part
> > - statusCode = Integer.parseInt (st.nextToken());
> > - StringBuffer sb = new StringBuffer(128);
> > - while (st.hasMoreTokens()) {
> > - sb.append (st.nextToken());
> > - if (st.hasMoreTokens()) {
> > - sb.append(" ");
> > + int versionEnd = -1;
> > + int codeStart = -1;
> > + int codeEnd = -1;
> > + int stringStart = -1;
> > +
> > + for (count = 0, b = bInStream.read(); b != '\n'
> > && b != -1; b = bInStream.read()) {
> > + if (b != '\r') {
> > + if (b == ' ') {
> > + if (versionEnd == -1) {
> > + versionEnd = count;
> > + } else if (codeStart != -1 &&
> > codeEnd == -1) {
> > + codeEnd = count;
> > + }
> > + } else {
> > + if (versionEnd != -1 && codeStart == -1) {
> > + codeStart = count;
> > + } else if (codeEnd != -1 &&
> > stringStart == -1) {
> > + stringStart = count;
> > + }
> > + }
> > + if (count >= linebuf.length) {
> > + byte[] newbuf = new byte[linebuf.length *
2];
> > + System.arraycopy(linebuf, 0, newbuf,
> > 0, linebuf.length);
> > + linebuf = newbuf;
> > + }
> > + linebuf[count++] = (byte) b;
> > }
> > }
> > - statusString = sb.toString();
> > - }
> > - catch (Exception e) {
> > + if (b == -1)
> > + throw new Exception("Reached end of stream
> > while reading HTTP response status");
> > + versionString = new String(linebuf, 0,
> > versionEnd, ISO_8859_1);
> > + statusCode = Integer.parseInt(new
> > String(linebuf, codeStart, codeEnd - codeStart, ISO_8859_1));
> > + statusString = new String(linebuf, stringStart,
> > count - stringStart, ISO_8859_1);
> > + } catch (Exception e) {
> > throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> > - "Error parsing HTTP status line \"" + line +
> > "\": " + e, e);
> > + "Error parsing HTTP status line \"" + new
> > String(linebuf, 0, count, ISO_8859_1) + "\": " + e, e);
> > }
> >
> > - /* Read the entire response (following the status line)
> > - * into a byte array. */
> > - ByteArrayDataSource ds = new ByteArrayDataSource(bInStream,
> > - Constants.HEADERVAL_DEFAULT_CHARSET);
> > -
> > - /* Extract the headers, content type and content length. */
> > - byte[] bytes = ds.toByteArray();
> > + /* Read the HTTP headers. */
> > Hashtable respHeaders = new Hashtable();
> > int respContentLength = -1;
> > String respContentType = null;
> >
> > - int nameStart = 0;
> > - int nameEnd = 0;
> > - int valStart = 0;
> > - boolean parsingName = true;
> > - int offset;
> > -
> > - for (offset = 0; offset < bytes.length; offset++) {
> > - if (bytes[offset] == '\n') {
> > - if (nameStart >= nameEnd)
> > + try {
> > + // Read all headers
> > + for (;;) {
> > + // Read and parse one header
> > + int nameEnd = -1;
> > + int valStart = -1;
> > + for (count = 0, b = bInStream.read(); b !=
> > '\n' && b != -1; b = bInStream.read()) {
> > + if (b != '\r') {
> > + if (nameEnd == -1 && b == ':') {
> > + nameEnd = count;
> > + } else if (nameEnd != -1 && valStart
> > == -1 && b != ' ' & b != '\t') {
> > + valStart = count;
> > + }
> > + if (count >= linebuf.length) {
> > + byte[] newbuf = new
> > byte[linebuf.length * 2];
> > + System.arraycopy(linebuf, 0,
> > newbuf, 0, linebuf.length);
> > + linebuf = newbuf;
> > + }
> > + linebuf[count++] = (byte) b;
> > + }
> > + }
> > + if (b == -1)
> > + throw new Exception("Reached end of
> > stream while reading HTTP response header");
> > + if (count == 0) // Read the header/entity
separator
> > break;
> > - String name = new String(bytes, nameStart,
> > nameEnd-nameStart+1);
> > -
> > - // Remove trailing ; to prevent ContextType
> > from throwing exception
> > - int valueLen = offset - valStart -1;
> > + if (nameEnd == -1 || valStart == -1)
> > + throw new Exception("Incorrectly formed
> > HTTP response header");
> >
> > - if (valueLen > 0 && bytes[offset-1] == ';')
> > - valueLen--;
> > + String name = new String(linebuf, 0,
> > nameEnd, ISO_8859_1);
> > + // Remove trailing ; to prevent ContentType
> > from throwing exception
> > + if (linebuf[count - 1] == ';')
> > + --count;
> > + String value = new String(linebuf, valStart,
> > count - valStart, ISO_8859_1);
> >
> > - String value = new String(bytes, valStart,
valueLen);
> > if
> > (name.equalsIgnoreCase(Constants.HEADER_CONTENT_LENGTH))
> > respContentLength = Integer.parseInt(value);
> > else if
> > (name.equalsIgnoreCase(Constants.HEADER_CONTENT_TYPE))
> > @@ -556,27 +594,11 @@
> > }
> > }
> > }
> > - parsingName = true;
> > - nameStart = offset+1;
> > }
> > - else if (bytes[offset] != '\r') {
> > - if (parsingName) {
> > - if (bytes[offset] == ':') {
> > - parsingName = false;
> > - nameEnd = offset - 1;
> > - if ((offset != bytes.length-1) &&
> > - bytes[offset+1] == ' ')
> > - offset++;
> > - valStart = offset+1;
> > - }
> > - }
> > - }
> > - } // End of for
> > -
> > - InputStream is = ds.getInputStream();
> > - is.skip(offset + 1);
> > - if (respContentLength < 0)
> > - respContentLength = ds.getSize() - offset - 1;
> > + } catch (Exception e) {
> > + throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> > + "Error parsing HTTP header line \"" + new
> > String(linebuf, 0, count, ISO_8859_1) + "\": " + e, e);
> > + }
> >
> > /* Handle redirect here */
> > if (statusCode >= HttpURLConnection.HTTP_MULT_CHOICE &&
> > @@ -595,11 +617,6 @@
> > }
> > }
> >
> > - /* If required, capture a copy of the response. */
> > - if (responseCopy != null) {
> > -
> > responseCopy.append(line).append("\r\n").append(new
> > String(bytes)); /* May get junk due to actual encoding */
> > - }
> > -
> > // TODO: process differently depending on statusCode
> > and respContentLength
> > // (TransportMessage does not even get statusCode)
> > // e.g. statusCode 401 is Unauthorized
> > @@ -612,13 +629,18 @@
> > // Create response SOAPContext.
> > ctx = new SOAPContext();
> > // Read content.
> > - response = new TransportMessage(is, respContentLength,
> > + response = new TransportMessage(bInStream,
> > respContentLength,
> > respContentType,
> > ctx, respHeaders);
> > // Extract envelope and SOAPContext
> > response.read();
> > } catch (MessagingException me) {
> > throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> > "Error parsing response:
> > " + me, me);
> > + }
> > +
> > + /* If required, capture a copy of the response. */
> > + if (responseCopy != null) {
> > + responseCopy.append(new
> > String(response.getBytes())); /* May get junk due to actual
> > encoding */
> > }
> >
> > /* All done here! */
> >
> >
> >
> > 1.17 +51 -37
> > xml-soap/java/src/org/apache/soap/transport/TransportMessage.java
> >
> > Index: TransportMessage.java
> >
===================================================================
> > RCS file:
> > /home/cvs/xml-soap/java/src/org/apache/soap/transport/Transpor
> tMessage.java,v
> > retrieving revision 1.16
> > retrieving revision 1.17
> > diff -u -r1.16 -r1.17
> > --- TransportMessage.java 6 Sep 2002 17:02:58 -0000 1.16
> > +++ TransportMessage.java 12 Nov 2002 14:15:38 -0000 1.17
> > @@ -128,25 +128,36 @@
> > this.ctx = ctx;
> > this.contentType = contentType;
> >
> > - if (contentLength < 0)
> > - throw new SOAPException
(Constants.FAULT_CODE_PROTOCOL,
> > - "Content length must
> > be specified.");
> > -
> > - bytes = new byte[contentLength];
> > - int offset = 0;
> > - int bytesRead = 0;
> > -
> > - // We're done reading when we get all the content
> > OR when the stream
> > - // returns a -1.
> > - while ((offset < contentLength) && (bytesRead >= 0)) {
> > - bytesRead = is.read(bytes, offset,
> > contentLength - offset);
> > - offset += bytesRead;
> > - }
> > - if (offset < contentLength)
> > - throw new SOAPException
(Constants.FAULT_CODE_PROTOCOL,
> > - "Premature end of stream. Data is
> > truncated. Read "
> > - + offset + " bytes successfully, expected
"
> > - + contentLength);
> > + bytes = new byte[contentLength >= 0 ?
> > contentLength : 4096];
> > + if (contentLength != 0) {
> > + int offset = 0;
> > + int bytesRead = 0;
> > +
> > + // We're done reading when we get all the
> > content OR when the stream
> > + // returns a -1.
> > + while ((contentLength < 0 || offset <
> > contentLength) && (bytesRead >= 0)) {
> > + bytesRead = is.read(bytes, offset,
> > bytes.length - offset);
> > + offset += bytesRead;
> > + if (contentLength < 0 && offset >= bytes.length)
{
> > + byte[] newbuf = new byte[bytes.length * 2];
> > + System.arraycopy(bytes, 0, newbuf, 0,
> > bytes.length);
> > + bytes = newbuf;
> > + }
> > + }
> > +
> > + if (contentLength < 0) {
> > + if (offset < bytes.length) {
> > + byte[] newbuf = new byte[offset];
> > + System.arraycopy(bytes, 0, newbuf, 0,
offset);
> > + bytes = newbuf;
> > + }
> > + } else if (offset < contentLength) {
> > + throw new SOAPException
> > (Constants.FAULT_CODE_PROTOCOL,
> > + "Premature end of stream. Data
> > is truncated. Read "
> > + + offset + " bytes
> > successfully, expected "
> > + + contentLength);
> > + }
> > + }
> > }
> >
> > /**
> > @@ -284,7 +295,7 @@
> > }
> >
> > // If the root part is text, extract it as a String.
> > - // Note that we could use JAF's help to do this
> > (see getEnvelope())
> > + // Note that we could use JAF's help to do this
> > (see save())
> > // but implementing it ourselves is safer and faster.
> > if (rootContentType.match("text/*")) {
> > String charset =
> > rootContentType.getParameter("charset");
> > @@ -323,9 +334,11 @@
> > */
> > public void save()
> > throws MessagingException, IOException {
> > - /* If an envelope was provided as a string, set it
> > as the root part.
> > - * Otherwise, assume that the SOAPContext already
> > has a root part.
> > + /*
> > + * If an envelope was provided as a string, set it
> > as the root part.
> > * If there was already a root part, preserve its
> > content-type.
> > + * Otherwise, assume that the SOAPContext already
> > has a root part,
> > + * and try to use it as the envelope.
> > */
> > String rootContentType = null;
> > if (ctx.isRootPartSet()) {
> > @@ -339,8 +352,18 @@
> > }
> > if (rootContentType == null)
> > rootContentType =
> > Constants.HEADERVAL_CONTENT_TYPE_UTF8;
> > - if (getEnvelope() != null)
> > + if (getEnvelope() != null) {
> > ctx.setRootPart(envelope, rootContentType);
> > + } else {
> > + MimeBodyPart rootPart = ctx.getRootPart();
> > + if (rootPart != null) {
> > + if (rootPart.isMimeType("text/*")) {
> > + ByteArrayDataSource ds = new
> > ByteArrayDataSource(
> > + rootPart.getInputStream(),
> > rootPart.getContentType());
> > + envelope = ds.getText();
> > + }
> > + }
> > + }
> >
> > // Print the whole response to a byte array.
> > ByteArrayOutputStream payload =
> > @@ -428,20 +451,9 @@
> > }
> >
> > /**
> > - * Get SOAP Envelope/root part as a String.
> > - * This method will extract the root part from the
> > SOAPContext as a String
> > - * if there is no SOAP Envelope.
> > + * Get SOAP Envelope as a String.
> > */
> > - public String getEnvelope() throws MessagingException,
> > IOException {
> > - if (envelope == null) {
> > - MimeBodyPart rootPart = ctx.getRootPart();
> > - if (rootPart != null)
> > - if (rootPart.isMimeType("text/*")) {
> > - ByteArrayDataSource ds = new
> > ByteArrayDataSource(
> > - rootPart.getInputStream(),
> > rootPart.getContentType());
> > - envelope = ds.getText();
> > - }
> > - }
> > + public String getEnvelope() {
> > return envelope;
> > }
> >
> > @@ -449,7 +461,7 @@
> > * Get SOAP Envelope/root part as a Reader. Returns
> > null if the root part
> > * is not text.
> > */
> > - public Reader getEnvelopeReader() throws
> > MessagingException, IOException {
> > + public Reader getEnvelopeReader() {
> > if (getEnvelope() == null)
> > return null;
> > else
> > @@ -530,6 +542,8 @@
> >
> > /**
> > * Set the byte array of the response.
> > + *
> > + * @deprecated After 2.3.1
> > */
> > public void readFully(InputStream is) throws IOException {
> > offset = 0;
> >
> >
> >
> > 1.29 +19 -16
> > xml-soap/java/src/org/apache/soap/transport/http/SOAPHTTPConne
> > ction.java
> >
> > Index: SOAPHTTPConnection.java
> >
===================================================================
> > RCS file:
> > /home/cvs/xml-soap/java/src/org/apache/soap/transport/http/SOA
> PHTTPConnection.java,v
> > retrieving revision 1.28
> > retrieving revision 1.29
> > diff -u -r1.28 -r1.29
> > --- SOAPHTTPConnection.java 16 Oct 2002 04:16:15 -0000 1.28
> > +++ SOAPHTTPConnection.java 12 Nov 2002 14:15:38 -0000 1.29
> > @@ -84,9 +84,7 @@
> > * @author Arek Wnukowski (apache@wnuko.demon.co.uk)
> > */
> > public class SOAPHTTPConnection implements SOAPTransport {
> > - private BufferedReader responseReader;
> > - private Hashtable responseHeaders;
> > - private SOAPContext responseSOAPContext;
> > + private TransportMessage response;
> >
> > private String httpProxyHost;
> > private int httpProxyPort = 80;
> > @@ -369,7 +367,6 @@
> > "Basic " +
> > HTTPUtils.encodeAuth(proxyUserName, proxyPassword));
> > }
> >
> > - TransportMessage response;
> > try
> > {
> > TransportMessage msg = new
> > TransportMessage(payload, ctx, headers);
> > @@ -385,18 +382,12 @@
> > throw new IOException ("Failed to encode mime
> > multipart: " + uee);
> > }
> >
> > - Reader envReader = response.getEnvelopeReader();
> > - if (envReader != null)
> > - responseReader = new BufferedReader(envReader);
> > - else
> > - responseReader = null;
> > - responseSOAPContext = response.getSOAPContext();
> > - responseHeaders = response.getHeaders();
> > if (maintainSession) {
> > // look for Set-Cookie2 and Set-Cookie headers and
> > save them.
> > // Only update my state iff the header is there ..
> > otherwise
> > // leave the current
> > // Note: Header is case-insensitive
> > + Hashtable responseHeaders = response.getHeaders();
> > String hdr;
> >
> > hdr = HTTPUtils.getHeaderValue (responseHeaders,
> > "Set-Cookie2");
> > @@ -421,8 +412,6 @@
> > }
> > } catch (IllegalArgumentException e) {
> > throw new SOAPException
> > (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> > - } catch (MessagingException e) {
> > - throw new SOAPException
> > (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> > } catch (IOException e) {
> > throw new SOAPException
> > (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> > }
> > @@ -436,7 +425,21 @@
> > * possible.
> > */
> > public BufferedReader receive () {
> > - return responseReader;
> > + if (response != null) {
> > + Reader envReader = response.getEnvelopeReader();
> > + if (envReader != null)
> > + return new BufferedReader(envReader);
> > + }
> > + return null;
> > + }
> > +
> > + /**
> > + * Returns the SOAP envelope.
> > + *
> > + * @return The SOAP envelope.
> > + */
> > + public String getEnvelope() {
> > + return response != null ? response.getEnvelope() : null;
> > }
> >
> > /**
> > @@ -445,7 +448,7 @@
> > * @return a hashtable containing all the headers
> > */
> > public Hashtable getHeaders () {
> > - return responseHeaders;
> > + return response != null ? response.getHeaders() : null;
> > }
> >
> > /**
> > @@ -454,6 +457,6 @@
> > * @return response SOAPContext
> > */
> > public SOAPContext getResponseSOAPContext () {
> > - return responseSOAPContext;
> > + return response != null ? response.getSOAPContext() : null;
> > }
> > }
> >
> >
> >
> >
> > --
> > To unsubscribe, e-mail:
<ma...@xml.apache.org>
> > For additional commands, e-mail:
<ma...@xml.apache.org>
> >
>
> --
> To unsubscribe, e-mail: <ma...@xml.apache.org>
> For additional commands, e-mail: <ma...@xml.apache.org>
>
>
--
To unsubscribe, e-mail: <ma...@xml.apache.org>
For additional commands, e-mail: <ma...@xml.apache.org>
Re: cvs commit: xml-soap/java/src/org/apache/soap/transport/http
SOAPHTTPConnection.java
Posted by Scott Nichol <sn...@scottnichol.com>.
This is the case where the message has a Content-Length header
specifying 0 octets. I create the byte array of that length, but there
is no reason to read, since I want 0 bytes, which is what I already
have.
Scott Nichol
----- Original Message -----
From: "Pavel Ausianik" <Pa...@epam.com>
To: <so...@xml.apache.org>
Sent: Tuesday, November 12, 2002 10:53 AM
Subject: RE: cvs commit:
xml-soap/java/src/org/apache/soap/transport/http SOAPHTTPConnection.java
> Scott,
>
> i don't know if this makes sence, but logic little bit strange, in
case
> contentLength=0. See buffer has been created, but as I can see it is
not
> used anymore since the following block finishes at the end. Should be
there
> condition to go inside and read from buffer?
>
> bytes = new byte[contentLength >= 0 ? contentLength : 4096];
> if (contentLength != 0) {
>
> Pavel
>
> > -----Original Message-----
> > From: snichol@apache.org [mailto:snichol@apache.org]
> > Sent: Tuesday, November 12, 2002 4:16 PM
> > To: xml-soap-cvs@apache.org
> > Subject: cvs commit:
xml-soap/java/src/org/apache/soap/transport/http
> > SOAPHTTPConnection.java
> >
> >
> > snichol 2002/11/12 06:15:38
> >
> > Modified: java/src/org/apache/soap/util/net HTTPUtils.java
> > java/src/org/apache/soap/transport
> > TransportMessage.java
> > java/src/org/apache/soap/transport/http
> > SOAPHTTPConnection.java
> > Log:
> > Reduce the number of times a response is copied in part or in
whole.
> > Improve error reporting during response parsing.
> > Support services that shutdown the write half of the socket
> > rather than
> > provide a Content-Length header.
> > Add getEnvelope to SOAPHTTPConnection. (The method will
> > also be added
> > to SOAPTransport soon.)
> >
> > Revision Changes Path
> > 1.36 +104 -82
> > xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java
> >
> > Index: HTTPUtils.java
> >
===================================================================
> > RCS file:
> >
/home/cvs/xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java,v
> > retrieving revision 1.35
> > retrieving revision 1.36
> > diff -u -r1.35 -r1.36
> > --- HTTPUtils.java 18 Oct 2002 20:30:54 -0000 1.35
> > +++ HTTPUtils.java 12 Nov 2002 14:15:38 -0000 1.36
> > @@ -57,21 +57,30 @@
> >
> > package org.apache.soap.util.net;
> >
> > -import java.io.*;
> > -import java.lang.reflect.*;
> > -import java.net.*;
> > -import java.util.*;
> > -
> > -import javax.mail.*;
> > -import javax.mail.internet.*;
> > -import javax.activation.*;
> > +import java.io.BufferedInputStream;
> > +import java.io.BufferedOutputStream;
> > +import java.io.BufferedReader;
> > +import java.io.InputStream;
> > +import java.io.IOException;
> > +import java.io.OutputStream;
> > +import java.io.UnsupportedEncodingException;
> > +import java.lang.reflect.InvocationTargetException;
> > +import java.lang.reflect.Method;
> > +import java.net.HttpURLConnection;
> > +import java.net.Socket;
> > +import java.net.URL;
> > +import java.util.Enumeration;
> > +import java.util.Hashtable;
> > +import java.util.StringTokenizer;
> >
> > -import org.apache.soap.*;
> > +import javax.mail.MessagingException;
> > +
> > +import org.apache.soap.Constants;
> > +import org.apache.soap.SOAPException;
> > import org.apache.soap.encoding.soapenc.Base64;
> > -import org.apache.soap.rpc.*;
> > -import org.apache.soap.transport.*;
> > +import org.apache.soap.rpc.SOAPContext;
> > +import org.apache.soap.transport.TransportMessage;
> > import org.apache.soap.util.MutableBoolean;
> > -import org.apache.soap.util.mime.*;
> >
> > /**
> > * A bunch of utility stuff for doing HTTP things.
> > @@ -91,6 +100,7 @@
> > private static final String HTTP_VERSION = "1.0";
> > private static final int HTTP_DEFAULT_PORT = 80;
> > private static final int HTTPS_DEFAULT_PORT = 443;
> > + private static final String ISO_8859_1 = "8859_1";
> >
> > public static final int DEFAULT_OUTPUT_BUFFER_SIZE =
> > 8 * 1024;
> >
> > @@ -100,7 +110,7 @@
> > public static String encodeAuth(String userName, String
password)
> > throws SOAPException {
> > try {
> > - return Base64.encode((userName + ":" +
> > password).getBytes("8859_1"));
> > + return Base64.encode((userName + ":" +
> > password).getBytes(ISO_8859_1));
> > } catch (UnsupportedEncodingException e) {
> > throw new SOAPException
> > (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> > }
> > @@ -482,65 +492,93 @@
> > bOutStream.flush();
> >
> > BufferedInputStream bInStream = new
> > BufferedInputStream(inStream);
> > + byte[] linebuf = new byte[1024];
> > + int count = 0;
> > + int b;
> > +
> > /* Read the response status line. */
> > + String versionString = null;
> > int statusCode = 0;
> > String statusString = null;
> > - StringBuffer linebuf = new StringBuffer(128);
> > - int b = 0;
> > - while (b != '\n' && b != -1) {
> > - b = bInStream.read();
> > - if (b != '\n' && b != '\r' && b != -1)
> > - linebuf.append((char)b);
> > - }
> > - String line = linebuf.toString();
> > +
> > try {
> > - StringTokenizer st = new StringTokenizer(line);
> > - st.nextToken(); // ignore version part
> > - statusCode = Integer.parseInt (st.nextToken());
> > - StringBuffer sb = new StringBuffer(128);
> > - while (st.hasMoreTokens()) {
> > - sb.append (st.nextToken());
> > - if (st.hasMoreTokens()) {
> > - sb.append(" ");
> > + int versionEnd = -1;
> > + int codeStart = -1;
> > + int codeEnd = -1;
> > + int stringStart = -1;
> > +
> > + for (count = 0, b = bInStream.read(); b != '\n'
> > && b != -1; b = bInStream.read()) {
> > + if (b != '\r') {
> > + if (b == ' ') {
> > + if (versionEnd == -1) {
> > + versionEnd = count;
> > + } else if (codeStart != -1 &&
> > codeEnd == -1) {
> > + codeEnd = count;
> > + }
> > + } else {
> > + if (versionEnd != -1 && codeStart == -1) {
> > + codeStart = count;
> > + } else if (codeEnd != -1 &&
> > stringStart == -1) {
> > + stringStart = count;
> > + }
> > + }
> > + if (count >= linebuf.length) {
> > + byte[] newbuf = new byte[linebuf.length *
2];
> > + System.arraycopy(linebuf, 0, newbuf,
> > 0, linebuf.length);
> > + linebuf = newbuf;
> > + }
> > + linebuf[count++] = (byte) b;
> > }
> > }
> > - statusString = sb.toString();
> > - }
> > - catch (Exception e) {
> > + if (b == -1)
> > + throw new Exception("Reached end of stream
> > while reading HTTP response status");
> > + versionString = new String(linebuf, 0,
> > versionEnd, ISO_8859_1);
> > + statusCode = Integer.parseInt(new
> > String(linebuf, codeStart, codeEnd - codeStart, ISO_8859_1));
> > + statusString = new String(linebuf, stringStart,
> > count - stringStart, ISO_8859_1);
> > + } catch (Exception e) {
> > throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> > - "Error parsing HTTP status line \"" + line +
> > "\": " + e, e);
> > + "Error parsing HTTP status line \"" + new
> > String(linebuf, 0, count, ISO_8859_1) + "\": " + e, e);
> > }
> >
> > - /* Read the entire response (following the status line)
> > - * into a byte array. */
> > - ByteArrayDataSource ds = new ByteArrayDataSource(bInStream,
> > - Constants.HEADERVAL_DEFAULT_CHARSET);
> > -
> > - /* Extract the headers, content type and content length. */
> > - byte[] bytes = ds.toByteArray();
> > + /* Read the HTTP headers. */
> > Hashtable respHeaders = new Hashtable();
> > int respContentLength = -1;
> > String respContentType = null;
> >
> > - int nameStart = 0;
> > - int nameEnd = 0;
> > - int valStart = 0;
> > - boolean parsingName = true;
> > - int offset;
> > -
> > - for (offset = 0; offset < bytes.length; offset++) {
> > - if (bytes[offset] == '\n') {
> > - if (nameStart >= nameEnd)
> > + try {
> > + // Read all headers
> > + for (;;) {
> > + // Read and parse one header
> > + int nameEnd = -1;
> > + int valStart = -1;
> > + for (count = 0, b = bInStream.read(); b !=
> > '\n' && b != -1; b = bInStream.read()) {
> > + if (b != '\r') {
> > + if (nameEnd == -1 && b == ':') {
> > + nameEnd = count;
> > + } else if (nameEnd != -1 && valStart
> > == -1 && b != ' ' & b != '\t') {
> > + valStart = count;
> > + }
> > + if (count >= linebuf.length) {
> > + byte[] newbuf = new
> > byte[linebuf.length * 2];
> > + System.arraycopy(linebuf, 0,
> > newbuf, 0, linebuf.length);
> > + linebuf = newbuf;
> > + }
> > + linebuf[count++] = (byte) b;
> > + }
> > + }
> > + if (b == -1)
> > + throw new Exception("Reached end of
> > stream while reading HTTP response header");
> > + if (count == 0) // Read the header/entity
separator
> > break;
> > - String name = new String(bytes, nameStart,
> > nameEnd-nameStart+1);
> > -
> > - // Remove trailing ; to prevent ContextType
> > from throwing exception
> > - int valueLen = offset - valStart -1;
> > + if (nameEnd == -1 || valStart == -1)
> > + throw new Exception("Incorrectly formed
> > HTTP response header");
> >
> > - if (valueLen > 0 && bytes[offset-1] == ';')
> > - valueLen--;
> > + String name = new String(linebuf, 0,
> > nameEnd, ISO_8859_1);
> > + // Remove trailing ; to prevent ContentType
> > from throwing exception
> > + if (linebuf[count - 1] == ';')
> > + --count;
> > + String value = new String(linebuf, valStart,
> > count - valStart, ISO_8859_1);
> >
> > - String value = new String(bytes, valStart,
valueLen);
> > if
> > (name.equalsIgnoreCase(Constants.HEADER_CONTENT_LENGTH))
> > respContentLength = Integer.parseInt(value);
> > else if
> > (name.equalsIgnoreCase(Constants.HEADER_CONTENT_TYPE))
> > @@ -556,27 +594,11 @@
> > }
> > }
> > }
> > - parsingName = true;
> > - nameStart = offset+1;
> > }
> > - else if (bytes[offset] != '\r') {
> > - if (parsingName) {
> > - if (bytes[offset] == ':') {
> > - parsingName = false;
> > - nameEnd = offset - 1;
> > - if ((offset != bytes.length-1) &&
> > - bytes[offset+1] == ' ')
> > - offset++;
> > - valStart = offset+1;
> > - }
> > - }
> > - }
> > - } // End of for
> > -
> > - InputStream is = ds.getInputStream();
> > - is.skip(offset + 1);
> > - if (respContentLength < 0)
> > - respContentLength = ds.getSize() - offset - 1;
> > + } catch (Exception e) {
> > + throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> > + "Error parsing HTTP header line \"" + new
> > String(linebuf, 0, count, ISO_8859_1) + "\": " + e, e);
> > + }
> >
> > /* Handle redirect here */
> > if (statusCode >= HttpURLConnection.HTTP_MULT_CHOICE &&
> > @@ -595,11 +617,6 @@
> > }
> > }
> >
> > - /* If required, capture a copy of the response. */
> > - if (responseCopy != null) {
> > -
> > responseCopy.append(line).append("\r\n").append(new
> > String(bytes)); /* May get junk due to actual encoding */
> > - }
> > -
> > // TODO: process differently depending on statusCode
> > and respContentLength
> > // (TransportMessage does not even get statusCode)
> > // e.g. statusCode 401 is Unauthorized
> > @@ -612,13 +629,18 @@
> > // Create response SOAPContext.
> > ctx = new SOAPContext();
> > // Read content.
> > - response = new TransportMessage(is, respContentLength,
> > + response = new TransportMessage(bInStream,
> > respContentLength,
> > respContentType,
> > ctx, respHeaders);
> > // Extract envelope and SOAPContext
> > response.read();
> > } catch (MessagingException me) {
> > throw new SOAPException(Constants.FAULT_CODE_CLIENT,
> > "Error parsing response:
> > " + me, me);
> > + }
> > +
> > + /* If required, capture a copy of the response. */
> > + if (responseCopy != null) {
> > + responseCopy.append(new
> > String(response.getBytes())); /* May get junk due to actual
> > encoding */
> > }
> >
> > /* All done here! */
> >
> >
> >
> > 1.17 +51 -37
> > xml-soap/java/src/org/apache/soap/transport/TransportMessage.java
> >
> > Index: TransportMessage.java
> >
===================================================================
> > RCS file:
> > /home/cvs/xml-soap/java/src/org/apache/soap/transport/Transpor
> tMessage.java,v
> > retrieving revision 1.16
> > retrieving revision 1.17
> > diff -u -r1.16 -r1.17
> > --- TransportMessage.java 6 Sep 2002 17:02:58 -0000 1.16
> > +++ TransportMessage.java 12 Nov 2002 14:15:38 -0000 1.17
> > @@ -128,25 +128,36 @@
> > this.ctx = ctx;
> > this.contentType = contentType;
> >
> > - if (contentLength < 0)
> > - throw new SOAPException
(Constants.FAULT_CODE_PROTOCOL,
> > - "Content length must
> > be specified.");
> > -
> > - bytes = new byte[contentLength];
> > - int offset = 0;
> > - int bytesRead = 0;
> > -
> > - // We're done reading when we get all the content
> > OR when the stream
> > - // returns a -1.
> > - while ((offset < contentLength) && (bytesRead >= 0)) {
> > - bytesRead = is.read(bytes, offset,
> > contentLength - offset);
> > - offset += bytesRead;
> > - }
> > - if (offset < contentLength)
> > - throw new SOAPException
(Constants.FAULT_CODE_PROTOCOL,
> > - "Premature end of stream. Data is
> > truncated. Read "
> > - + offset + " bytes successfully, expected
"
> > - + contentLength);
> > + bytes = new byte[contentLength >= 0 ?
> > contentLength : 4096];
> > + if (contentLength != 0) {
> > + int offset = 0;
> > + int bytesRead = 0;
> > +
> > + // We're done reading when we get all the
> > content OR when the stream
> > + // returns a -1.
> > + while ((contentLength < 0 || offset <
> > contentLength) && (bytesRead >= 0)) {
> > + bytesRead = is.read(bytes, offset,
> > bytes.length - offset);
> > + offset += bytesRead;
> > + if (contentLength < 0 && offset >= bytes.length)
{
> > + byte[] newbuf = new byte[bytes.length * 2];
> > + System.arraycopy(bytes, 0, newbuf, 0,
> > bytes.length);
> > + bytes = newbuf;
> > + }
> > + }
> > +
> > + if (contentLength < 0) {
> > + if (offset < bytes.length) {
> > + byte[] newbuf = new byte[offset];
> > + System.arraycopy(bytes, 0, newbuf, 0,
offset);
> > + bytes = newbuf;
> > + }
> > + } else if (offset < contentLength) {
> > + throw new SOAPException
> > (Constants.FAULT_CODE_PROTOCOL,
> > + "Premature end of stream. Data
> > is truncated. Read "
> > + + offset + " bytes
> > successfully, expected "
> > + + contentLength);
> > + }
> > + }
> > }
> >
> > /**
> > @@ -284,7 +295,7 @@
> > }
> >
> > // If the root part is text, extract it as a String.
> > - // Note that we could use JAF's help to do this
> > (see getEnvelope())
> > + // Note that we could use JAF's help to do this
> > (see save())
> > // but implementing it ourselves is safer and faster.
> > if (rootContentType.match("text/*")) {
> > String charset =
> > rootContentType.getParameter("charset");
> > @@ -323,9 +334,11 @@
> > */
> > public void save()
> > throws MessagingException, IOException {
> > - /* If an envelope was provided as a string, set it
> > as the root part.
> > - * Otherwise, assume that the SOAPContext already
> > has a root part.
> > + /*
> > + * If an envelope was provided as a string, set it
> > as the root part.
> > * If there was already a root part, preserve its
> > content-type.
> > + * Otherwise, assume that the SOAPContext already
> > has a root part,
> > + * and try to use it as the envelope.
> > */
> > String rootContentType = null;
> > if (ctx.isRootPartSet()) {
> > @@ -339,8 +352,18 @@
> > }
> > if (rootContentType == null)
> > rootContentType =
> > Constants.HEADERVAL_CONTENT_TYPE_UTF8;
> > - if (getEnvelope() != null)
> > + if (getEnvelope() != null) {
> > ctx.setRootPart(envelope, rootContentType);
> > + } else {
> > + MimeBodyPart rootPart = ctx.getRootPart();
> > + if (rootPart != null) {
> > + if (rootPart.isMimeType("text/*")) {
> > + ByteArrayDataSource ds = new
> > ByteArrayDataSource(
> > + rootPart.getInputStream(),
> > rootPart.getContentType());
> > + envelope = ds.getText();
> > + }
> > + }
> > + }
> >
> > // Print the whole response to a byte array.
> > ByteArrayOutputStream payload =
> > @@ -428,20 +451,9 @@
> > }
> >
> > /**
> > - * Get SOAP Envelope/root part as a String.
> > - * This method will extract the root part from the
> > SOAPContext as a String
> > - * if there is no SOAP Envelope.
> > + * Get SOAP Envelope as a String.
> > */
> > - public String getEnvelope() throws MessagingException,
> > IOException {
> > - if (envelope == null) {
> > - MimeBodyPart rootPart = ctx.getRootPart();
> > - if (rootPart != null)
> > - if (rootPart.isMimeType("text/*")) {
> > - ByteArrayDataSource ds = new
> > ByteArrayDataSource(
> > - rootPart.getInputStream(),
> > rootPart.getContentType());
> > - envelope = ds.getText();
> > - }
> > - }
> > + public String getEnvelope() {
> > return envelope;
> > }
> >
> > @@ -449,7 +461,7 @@
> > * Get SOAP Envelope/root part as a Reader. Returns
> > null if the root part
> > * is not text.
> > */
> > - public Reader getEnvelopeReader() throws
> > MessagingException, IOException {
> > + public Reader getEnvelopeReader() {
> > if (getEnvelope() == null)
> > return null;
> > else
> > @@ -530,6 +542,8 @@
> >
> > /**
> > * Set the byte array of the response.
> > + *
> > + * @deprecated After 2.3.1
> > */
> > public void readFully(InputStream is) throws IOException {
> > offset = 0;
> >
> >
> >
> > 1.29 +19 -16
> > xml-soap/java/src/org/apache/soap/transport/http/SOAPHTTPConne
> > ction.java
> >
> > Index: SOAPHTTPConnection.java
> >
===================================================================
> > RCS file:
> > /home/cvs/xml-soap/java/src/org/apache/soap/transport/http/SOA
> PHTTPConnection.java,v
> > retrieving revision 1.28
> > retrieving revision 1.29
> > diff -u -r1.28 -r1.29
> > --- SOAPHTTPConnection.java 16 Oct 2002 04:16:15 -0000 1.28
> > +++ SOAPHTTPConnection.java 12 Nov 2002 14:15:38 -0000 1.29
> > @@ -84,9 +84,7 @@
> > * @author Arek Wnukowski (apache@wnuko.demon.co.uk)
> > */
> > public class SOAPHTTPConnection implements SOAPTransport {
> > - private BufferedReader responseReader;
> > - private Hashtable responseHeaders;
> > - private SOAPContext responseSOAPContext;
> > + private TransportMessage response;
> >
> > private String httpProxyHost;
> > private int httpProxyPort = 80;
> > @@ -369,7 +367,6 @@
> > "Basic " +
> > HTTPUtils.encodeAuth(proxyUserName, proxyPassword));
> > }
> >
> > - TransportMessage response;
> > try
> > {
> > TransportMessage msg = new
> > TransportMessage(payload, ctx, headers);
> > @@ -385,18 +382,12 @@
> > throw new IOException ("Failed to encode mime
> > multipart: " + uee);
> > }
> >
> > - Reader envReader = response.getEnvelopeReader();
> > - if (envReader != null)
> > - responseReader = new BufferedReader(envReader);
> > - else
> > - responseReader = null;
> > - responseSOAPContext = response.getSOAPContext();
> > - responseHeaders = response.getHeaders();
> > if (maintainSession) {
> > // look for Set-Cookie2 and Set-Cookie headers and
> > save them.
> > // Only update my state iff the header is there ..
> > otherwise
> > // leave the current
> > // Note: Header is case-insensitive
> > + Hashtable responseHeaders = response.getHeaders();
> > String hdr;
> >
> > hdr = HTTPUtils.getHeaderValue (responseHeaders,
> > "Set-Cookie2");
> > @@ -421,8 +412,6 @@
> > }
> > } catch (IllegalArgumentException e) {
> > throw new SOAPException
> > (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> > - } catch (MessagingException e) {
> > - throw new SOAPException
> > (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> > } catch (IOException e) {
> > throw new SOAPException
> > (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
> > }
> > @@ -436,7 +425,21 @@
> > * possible.
> > */
> > public BufferedReader receive () {
> > - return responseReader;
> > + if (response != null) {
> > + Reader envReader = response.getEnvelopeReader();
> > + if (envReader != null)
> > + return new BufferedReader(envReader);
> > + }
> > + return null;
> > + }
> > +
> > + /**
> > + * Returns the SOAP envelope.
> > + *
> > + * @return The SOAP envelope.
> > + */
> > + public String getEnvelope() {
> > + return response != null ? response.getEnvelope() : null;
> > }
> >
> > /**
> > @@ -445,7 +448,7 @@
> > * @return a hashtable containing all the headers
> > */
> > public Hashtable getHeaders () {
> > - return responseHeaders;
> > + return response != null ? response.getHeaders() : null;
> > }
> >
> > /**
> > @@ -454,6 +457,6 @@
> > * @return response SOAPContext
> > */
> > public SOAPContext getResponseSOAPContext () {
> > - return responseSOAPContext;
> > + return response != null ? response.getSOAPContext() : null;
> > }
> > }
> >
> >
> >
> >
> > --
> > To unsubscribe, e-mail:
<ma...@xml.apache.org>
> > For additional commands, e-mail:
<ma...@xml.apache.org>
> >
>
> --
> To unsubscribe, e-mail: <ma...@xml.apache.org>
> For additional commands, e-mail: <ma...@xml.apache.org>
>
>