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: [EMAIL PROTECTED] [mailto:snichol@;apache.org] > Sent: Tuesday, November 12, 2002 4:16 PM > To: [EMAIL PROTECTED] > 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 ([EMAIL PROTECTED]) > */ > 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: <mailto:soap-dev-unsubscribe@;xml.apache.org> > For additional commands, e-mail: <mailto:soap-dev-help@;xml.apache.org> > -- To unsubscribe, e-mail: <mailto:soap-dev-unsubscribe@;xml.apache.org> For additional commands, e-mail: <mailto:soap-dev-help@;xml.apache.org>