snichol 2002/09/05 09:50:52 Modified: java/docs changes.html java/src/org/apache/soap/rpc SOAPContext.java java/src/org/apache/soap/server ServerUtils.java ServiceManagerClient.java java/src/org/apache/soap/server/http MessageRouterServlet.java RPCRouterServlet.java ServerHTTPUtils.java java/src/org/apache/soap/transport TransportMessage.java java/src/org/apache/soap/transport/http SOAPHTTPConnection.java java/src/org/apache/soap/util/net HTTPUtils.java Added: java/samples/gzip DeploymentDescriptor.xml GzipClient.java GzipService.java README testit.cmd testit.sh Log: Support gzip encoding for HTTP. This is enabled through SOAPContext for clients and the deployment descriptor for services. Revision Changes Path 1.44 +2 -0 xml-soap/java/docs/changes.html Index: changes.html =================================================================== RCS file: /home/cvs/xml-soap/java/docs/changes.html,v retrieving revision 1.43 retrieving revision 1.44 diff -u -r1.43 -r1.44 --- changes.html 30 Aug 2002 21:38:59 -0000 1.43 +++ changes.html 5 Sep 2002 16:50:51 -0000 1.44 @@ -74,6 +74,8 @@ document/literal encoding. Parameters will be serialized using document/literal style. Return values must be mapped by parameter name (the existing interop hack).</li> + <li>Support gzip encoding for HTTP. This is enabled through SOAPContext + for clients and the deployment descriptor for services.</li> </ul> </li> </ul> 1.1 xml-soap/java/samples/gzip/DeploymentDescriptor.xml Index: DeploymentDescriptor.xml =================================================================== <isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:gzip-sample"> <isd:provider type="java" scope="Application" methods="test"> <isd:java class="samples.gzip.GzipService"/> <isd:option key="gzip" value="true"/> <isd:option key="SessionRequired" value="false"/> </isd:provider> <isd:faultListener>org.apache.soap.server.DOMFaultListener</isd:faultListener> </isd:service> 1.1 xml-soap/java/samples/gzip/GzipClient.java Index: GzipClient.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2000 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 acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "SOAP" 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 name, without prior written * permission of the Apache Software Foundation. * * 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 and was * originally based on software copyright (c) 2000, International * Business Machines, Inc., http://www.apache.org. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package samples.gzip; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.net.URL; import java.util.Vector; import org.apache.soap.*; import org.apache.soap.rpc.*; /** * See README for info. * * @author Scott Nichol ([EMAIL PROTECTED]) */ public class GzipClient { public static void main (String[] args) throws Exception { if (args.length != 3) { System.err.println ("Usage: java " + GzipClient.class.getName() + " SOAP-router-URL file-to-send file-to-receive"); System.exit(1); } // Process the arguments. URL url = new URL(args[0]); String inFileName = args[1]; String outFileName = args[2]; // Check that the output file does not exist File outFile = new File(outFileName); if (outFile.exists()) throw new Exception("File " + outFileName + " already exists."); // Read the file to send File inFile = new File(inFileName); long inFileLength = inFile.length(); if (inFileLength > Integer.MAX_VALUE) throw new Exception("File " + inFileName + " is too long (" + inFileLength + " bytes). Specify a file <= " + Integer.MAX_VALUE + " bytes."); FileInputStream fis = new FileInputStream(inFile); byte[] inFileData = new byte[(int) inFileLength]; int totalbytes = 0; int bytes; while ((totalbytes < inFileData.length) && (bytes = fis.read(inFileData, totalbytes, inFileData.length - totalbytes)) != -1) { totalbytes += bytes; } fis.close(); System.out.println(totalbytes + " bytes read from " + inFileName + "."); // Build the call. SOAPContext ctx = new SOAPContext(); ctx.setGzip(true); Vector params = new Vector(); params.addElement(new Parameter("data", inFileData.getClass(), inFileData, null)); Call call = new Call("urn:gzip-sample", "test", params, null, Constants.NS_URI_SOAP_ENC, ctx); // Invoke the call and handle the response. Response resp = call.invoke(url, ""); if (resp.generatedFault()) { Fault fault = resp.getFault(); System.err.println("Generated fault: " + fault); } else { Parameter result = resp.getReturnValue(); byte[] outFileData = (byte[]) result.getValue(); FileOutputStream fos = new FileOutputStream(outFileName); fos.write(outFileData, 0, outFileData.length); fos.close(); System.out.println(outFileData.length + " bytes written to " + outFileName + "."); } } } 1.1 xml-soap/java/samples/gzip/GzipService.java Index: GzipService.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2000 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 acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "SOAP" 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 name, without prior written * permission of the Apache Software Foundation. * * 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 and was * originally based on software copyright (c) 2000, International * Business Machines, Inc., http://www.apache.org. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package samples.gzip; /** * Tests gzip. * * @author Scott Nichol ([EMAIL PROTECTED]) */ public class GzipService { /** * Echoes a byte array after replacing the last 1024 bytes with 0x5a. */ public byte[] test(byte[] data) { int offset = data.length > 1024 ? data.length - 1024 : 0; while (offset < data.length) data[offset++] = 0x5a; return data; } } 1.1 xml-soap/java/samples/gzip/README Index: README =================================================================== Service: ------- To install this service on an Apache-SOAP listener, you need to make the samples.addressbook package available on the Apache-SOAP listener's classpath. Then deploy this service by filling in the deployment template using the info in the deployment descriptor in this directory or by using the service manager client: java org.apache.soap.server.ServiceManagerClient routerURL deploy dd.xml where routerURL is the URL of the SOAP RPC router and dd.xml is the name of the deployment descriptor file. For example: java org.apache.soap.server.ServiceManagerClient \ http://localhost:8080/soap/servlet/rpcrouter deploy DeploymentDescriptor.xml Client: ------ There is one HTTP client that sends the contents of a file as a byte array and writes the response, which is an echo of the original file with the last 1024 bytes changed to 0x5a, to a new file. Additional Client Classpath Requirements: ---------------------------------------- ../.. Explanation: ----------- Basically an echo service, but configured with gzip encoding enabled on both the client and the server. Sample Usage: ------------ java samples.gzip.GzipClient \ http://localhost:8080/soap/servlet/rpcrouter GzipClient.java return.dat 1.1 xml-soap/java/samples/gzip/testit.cmd Index: testit.cmd =================================================================== @echo off echo This test assumes a server URL of http://localhost:8080/soap/servlet/rpcrouter echo Deploying the gzip service... java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter deploy DeploymentDescriptor.xml echo . echo Verify that it's there java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list echo . echo Running the gzip test del return.dat 2>nul java samples.gzip.GzipClient http://localhost:8080/soap/servlet/rpcrouter GzipClient.java return.dat echo . echo Undeploy it now java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter undeploy urn:gzip-sample echo . echo Verify that it's gone java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list 1.1 xml-soap/java/samples/gzip/testit.sh Index: testit.sh =================================================================== echo This test assumes a server URL of http://localhost:8080/soap/servlet/rpcrouter echo Deploying the gzip service... java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter deploy DeploymentDescriptor.xml echo echo Verify that it\'s there java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list echo echo Running the gzip test rm return.dat java samples.gzip.GzipClient http://localhost:8080/soap/servlet/rpcrouter GzipClient.java return.dat echo echo Undeploy it now java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter undeploy urn:gzip-sample echo echo Verify that it\'s gone java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter list 1.11 +40 -0 xml-soap/java/src/org/apache/soap/rpc/SOAPContext.java Index: SOAPContext.java =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/rpc/SOAPContext.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- SOAPContext.java 30 Aug 2002 21:39:00 -0000 1.10 +++ SOAPContext.java 5 Sep 2002 16:50:51 -0000 1.11 @@ -87,6 +87,8 @@ protected Hashtable deserializedMultiRef = new Hashtable(); protected String currentId = null; protected boolean docLitSerialization = false; + protected Boolean gzip = null; + protected Boolean acceptGzip = null; /** * This flag indicates if setRootPart() was called, so we can distinguish @@ -597,6 +599,44 @@ */ public void setDocLitSerialization(boolean docLitSerialization) { this.docLitSerialization = docLitSerialization; + } + + /** + * Gets whether gzip compression would be accepted. + * + * @return Whether gzip compression would be accepted. + * This is null if the value has not been set. + */ + public Boolean getAcceptGzip() { + return acceptGzip; + } + + /** + * Sets whether gzip compression would be accepted. + * + * @param Whether gzip compression would be accepted. + */ + public void setAcceptGzip(boolean acceptGzip) { + this.acceptGzip = acceptGzip ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Gets whether gzip compression is used in the byte array representation. + * + * @return Whether gzip compression is used in the byte array representation. + * This is null if the value has not been set. + */ + public Boolean getGzip() { + return gzip; + } + + /** + * Sets whether gzip compression is used in the byte array representation. + * + * @param gzip Whether gzip compression is used in the byte array representation. + */ + public void setGzip(boolean gzip) { + this.gzip = gzip ? Boolean.TRUE : Boolean.FALSE; } /** 1.10 +67 -1 xml-soap/java/src/org/apache/soap/server/ServerUtils.java Index: ServerUtils.java =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/server/ServerUtils.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- ServerUtils.java 2 May 2001 13:34:13 -0000 1.9 +++ ServerUtils.java 5 Sep 2002 16:50:52 -0000 1.10 @@ -68,6 +68,7 @@ import javax.xml.parsers.*; import org.w3c.dom.* ; import org.apache.soap.*; +import org.apache.soap.encoding.soapenc.SoapEncUtils; import org.apache.soap.rpc.*; import org.apache.soap.server.http.*; import org.apache.soap.util.*; @@ -81,6 +82,7 @@ * * @author Sanjiva Weerawarana * @author Wouter Cloetens + * @author Scott Nichol ([EMAIL PROTECTED]) */ public class ServerUtils { /** @@ -89,6 +91,12 @@ * transport level thing is wrong and throws a SOAPException if a * SOAP level thing is wrong. * + * @param xdb XML DOM document builder + * @param is Stream from which to read + * @param contentLength Length of message + * @param contentType Message content type, e.g. text/xml + * @param editor Hook to manipulate envelope + * @param ctx Context of current message * @return Envelope containing the SOAP envelope found in the request * * @exception SOAPException if a SOAP level thing goes wrong @@ -99,12 +107,42 @@ String contentType, EnvelopeEditor editor, SOAPContext ctx) + throws SOAPException, IOException, + IllegalArgumentException, MessagingException { + return readEnvelopeFromInputStream(xdb, is, contentLength, contentType, + editor, ctx, null); + } + + /** + * Read in stuff from the request stream and return the envelope. + * Returns null (and sets the error on the response stream) if a + * transport level thing is wrong and throws a SOAPException if a + * SOAP level thing is wrong. + * + * @param xdb XML DOM document builder + * @param is Stream from which to read + * @param contentLength Length of message + * @param contentType Message content type, e.g. text/xml + * @param editor Hook to manipulate envelope + * @param ctx Context of current message + * @param headers Transport and/or MIME headers + * @return Envelope containing the SOAP envelope found in the request + * + * @exception SOAPException if a SOAP level thing goes wrong + */ + public static Envelope readEnvelopeFromInputStream (DocumentBuilder xdb, + InputStream is, + int contentLength, + String contentType, + EnvelopeEditor editor, + SOAPContext ctx, + Hashtable headers) throws SOAPException, IOException, IllegalArgumentException, MessagingException { // Read input stream. TransportMessage reqMsg = new TransportMessage(is, contentLength, contentType, ctx, - null); + headers); // Extract envelope and SOAPContext reqMsg.read(); // Check Content-Type of root part of request to see if it's @@ -121,6 +159,13 @@ return reqMsg.unmarshall(xdb); } + /** + * Gets the Provider for the service in the deployment descriptor. + * + * @return Provider for the service in the deployment descriptor. + * + * @exception SOAPException if anything goes wrong + */ public static Provider loadProvider(DeploymentDescriptor dd, SOAPContext ctxt) throws SOAPException { @@ -151,5 +196,26 @@ "'" + className + "' isn't a provider"); return (Provider)newObj; + } + + /** + * Sets whether to gzip the response. + */ + public static void setResponseGzip(DeploymentDescriptor dd, + SOAPContext reqCtx, + SOAPContext resCtx) { + if (Boolean.TRUE.equals(reqCtx.getAcceptGzip())) { + // Request specified gzip OK + Hashtable props = dd.getProps(); + String gzip = props != null ? (String) props.get("gzip") : null; + resCtx.setGzip(gzip != null && SoapEncUtils.decodeBooleanValue(gzip)); + } else if (Boolean.FALSE.equals(reqCtx.getAcceptGzip())) { + // Request specified gzip not OK + resCtx.setGzip(false); + } else { + // Request specified nothing, for now do not gzip + // TODO: should accept be required? + resCtx.setGzip(false); + } } } 1.10 +1 -2 xml-soap/java/src/org/apache/soap/server/ServiceManagerClient.java Index: ServiceManagerClient.java =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/server/ServiceManagerClient.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- ServiceManagerClient.java 17 May 2001 18:25:52 -0000 1.9 +++ ServiceManagerClient.java 5 Sep 2002 16:50:52 -0000 1.10 @@ -130,8 +130,7 @@ if (resp.generatedFault ()) { Fault fault = resp.getFault (); System.out.println ("Ouch, the call failed: "); - System.out.println (" Fault Code = " + fault.getFaultCode ()); - System.out.println (" Fault String = " + fault.getFaultString ()); + System.out.println (fault.toString()); } return resp; } 1.36 +3 -1 xml-soap/java/src/org/apache/soap/server/http/MessageRouterServlet.java Index: MessageRouterServlet.java =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/server/http/MessageRouterServlet.java,v retrieving revision 1.35 retrieving revision 1.36 diff -u -r1.35 -r1.36 --- MessageRouterServlet.java 4 Aug 2002 02:47:31 -0000 1.35 +++ MessageRouterServlet.java 5 Sep 2002 16:50:52 -0000 1.36 @@ -273,7 +273,8 @@ req.getContentType(), req.getContentLength(), req.getInputStream(), - editor, res, reqCtx); + editor, res, reqCtx, + ServerHTTPUtils.getHeaders(req)); if (msgEnv == null) return; @@ -321,6 +322,7 @@ } provider.locate( dd, msgEnv, null, messageName, targetID, reqCtx ); + ServerUtils.setResponseGzip(dd, reqCtx, resCtx); provider.invoke( reqCtx, resCtx ); sres = new TransportMessage(null, resCtx, null); 1.40 +3 -1 xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java Index: RPCRouterServlet.java =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java,v retrieving revision 1.39 retrieving revision 1.40 diff -u -r1.39 -r1.40 --- RPCRouterServlet.java 4 Aug 2002 02:47:31 -0000 1.39 +++ RPCRouterServlet.java 5 Sep 2002 16:50:52 -0000 1.40 @@ -316,7 +316,8 @@ req.getInputStream(), editor, res, - reqCtx); + reqCtx, + ServerHTTPUtils.getHeaders(req)); if (callEnv == null) return; call = RPCRouter.extractCallFromEnvelope(serviceManager, callEnv, @@ -367,6 +368,7 @@ provider.locate( dd, callEnv, call, call.getMethodName(), fullTargetID, reqCtx ); + ServerUtils.setResponseGzip(dd, reqCtx, resCtx); provider.invoke( reqCtx, resCtx ); } catch (Throwable t) { 1.25 +55 -1 xml-soap/java/src/org/apache/soap/server/http/ServerHTTPUtils.java Index: ServerHTTPUtils.java =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/server/http/ServerHTTPUtils.java,v retrieving revision 1.24 retrieving revision 1.25 diff -u -r1.24 -r1.25 --- ServerHTTPUtils.java 11 Jul 2002 15:45:53 -0000 1.24 +++ ServerHTTPUtils.java 5 Sep 2002 16:50:52 -0000 1.25 @@ -182,6 +182,13 @@ * transport level thing is wrong and throws a SOAPException if a * SOAP level thing is wrong. * + * @param xdb XML DOM document builder + * @param contentType Message content type, e.g. text/xml + * @param contentLength Length of message + * @param requestStream Stream from which to read + * @param editor Hook to manipulate envelope + * @param res Stream to which to write response in case of error + * @param ctx Context of current message * @return Envelope containing the SOAP envelope found in the request * * @exception SOAPException if a SOAP level thing goes wrong @@ -196,11 +203,44 @@ HttpServletResponse res, SOAPContext ctx) throws SOAPException, IOException { + return readEnvelopeFromRequest(xdb, contentType, contentLength, + requestStream, editor, res, ctx, null); + } + + /** + * Read in stuff from the HTTP request stream and return the envelope. + * Returns null (and sets the error on the response stream) if a + * transport level thing is wrong and throws a SOAPException if a + * SOAP level thing is wrong. + * + * @param xdb XML DOM document builder + * @param contentType Message content type, e.g. text/xml + * @param contentLength Length of message + * @param requestStream Stream from which to read + * @param editor Hook to manipulate envelope + * @param res Stream to which to write response in case of error + * @param ctx Context of current message + * @param headers Transport and/or MIME headers + * @return Envelope containing the SOAP envelope found in the request + * + * @exception SOAPException if a SOAP level thing goes wrong + * @exception IOException if something fails while sending an + * error response + */ + public static Envelope readEnvelopeFromRequest (DocumentBuilder xdb, + String contentType, + int contentLength, + InputStream requestStream, + EnvelopeEditor editor, + HttpServletResponse res, + SOAPContext ctx, + Hashtable headers) + throws SOAPException, IOException { try { return ServerUtils.readEnvelopeFromInputStream (xdb, requestStream, contentLength, contentType, editor, - ctx); + ctx, headers); } catch (IllegalArgumentException e) { String msg = e.getMessage (); res.sendError (res.SC_BAD_REQUEST, "Error unmarshalling envelope: " + @@ -422,6 +462,20 @@ private static Hashtable getServiceParameters(DeploymentDescriptor dd) { Hashtable props = dd.getProps(); return (props != null) ? (Hashtable) props.clone() : null; + } + + /** + * Gets the HTTP headers for a request. + */ + public static Hashtable getHeaders(HttpServletRequest req) { + Enumeration e = req.getHeaderNames(); + Hashtable headers = new Hashtable(20); + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + String value = req.getHeader(name); + headers.put(name, value); + } + return headers; } /** 1.15 +56 -0 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/TransportMessage.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- TransportMessage.java 28 Aug 2002 18:32:28 -0000 1.14 +++ TransportMessage.java 5 Sep 2002 16:50:52 -0000 1.15 @@ -59,6 +59,8 @@ import java.io.*; import java.util.*; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; import javax.activation.*; import javax.mail.*; import javax.mail.internet.*; @@ -69,6 +71,7 @@ import org.apache.soap.encoding.*; import org.apache.soap.rpc.*; import org.apache.soap.util.*; +import org.apache.soap.util.net.HTTPUtils; import org.apache.soap.util.xml.*; import org.apache.soap.util.mime.*; import org.apache.soap.transport.EnvelopeEditor; @@ -77,6 +80,7 @@ * Transport type-independent encapsulation of SOAP message content. * * @author Wouter Cloetens + * @author Scott Nichol ([EMAIL PROTECTED]) */ public class TransportMessage implements Serializable { protected String contentType = null; @@ -215,6 +219,43 @@ if (cType == null) throw new SOAPException(Constants.FAULT_CODE_PROTOCOL, "Missing content type."); + + // Check encoding + String encoding = (String) HTTPUtils.getHeaderValue(headers, + "Accept-Encoding"); + if (encoding != null) + ctx.setAcceptGzip(encoding.indexOf("gzip") != -1); + + encoding = (String) HTTPUtils.getHeaderValue(headers, + "Content-Encoding"); + boolean gzip = false; + if (encoding != null && encoding.indexOf("gzip") != -1) + gzip = true; + ctx.setGzip(gzip); + if (gzip) { + // Inflate + ByteArrayInputStream bais = + new ByteArrayInputStream(bytes); + GZIPInputStream gzis = new GZIPInputStream(bais); + byte[] newbytes = new byte[bytes.length * 4]; + int totalread = 0; + int bytesread; + while ((bytesread = gzis.read(newbytes, totalread, + newbytes.length - totalread)) != -1) { + totalread += bytesread; + if (totalread >= newbytes.length) { + byte[] newerbytes = new byte[totalread * 4]; + System.arraycopy(newbytes, 0, newerbytes, 0, totalread); + newbytes = newerbytes; + } + } + gzis.close(); + bais.close(); + bytes = new byte[totalread]; + System.arraycopy(newbytes, 0, bytes, 0, totalread); + } + + // Start parsing MimeBodyPart rootPart; ContentType rootContentType; byte[] rootBytes; @@ -364,6 +405,21 @@ else valuebuf.append((char)bytes[offset]); } + } + // TODO: should not send for HTTP response + headers.put("Accept-Encoding", "x-gzip"); + if (Boolean.TRUE.equals(ctx.getGzip())) { + // Deflate + ByteArrayOutputStream baos = + new ByteArrayOutputStream(bytes.length * 2); + GZIPOutputStream gzos = new GZIPOutputStream(baos); + gzos.write(bytes, offset, bytes.length - offset); + gzos.close(); + baos.close(); + bytes = baos.toByteArray(); + offset = 0; + + headers.put("Content-Encoding", "x-gzip"); } } 1.26 +2 -22 xml-soap/java/src/org/apache/soap/transport/http/SOAPHTTPConnection.java Index: SOAPHTTPConnection.java =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/transport/http/SOAPHTTPConnection.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- SOAPHTTPConnection.java 30 Jul 2002 20:32:05 -0000 1.25 +++ SOAPHTTPConnection.java 5 Sep 2002 16:50:52 -0000 1.26 @@ -416,7 +416,7 @@ // Note: Header is case-insensitive String hdr; - hdr = getHeaderValue (responseHeaders, "Set-Cookie2"); + hdr = HTTPUtils.getHeaderValue (responseHeaders, "Set-Cookie2"); if (hdr != null) { Cookie[] hdrCookies = Cookie.parseCookies(sendTo, hdr); @@ -426,7 +426,7 @@ cookies2 = hdrCookies; } - hdr = getHeaderValue (responseHeaders, "Set-Cookie"); + hdr = HTTPUtils.getHeaderValue (responseHeaders, "Set-Cookie"); if (hdr != null) { Cookie[] hdrCookies = Cookie.parseCookies(sendTo, hdr); @@ -472,25 +472,5 @@ */ public SOAPContext getResponseSOAPContext () { return responseSOAPContext; - } - - /** - * Obtain a header value from the table using a case insensitive search. - * - * @param headers a colletion of headers from the http response - * @param headerName the name of the header to find - * @return the header value or null if not found - */ - private static String getHeaderValue (Hashtable headers, String headerName) - { - for (Enumeration enum = headers.keys (); enum.hasMoreElements ();) { - String key = (String) enum.nextElement(); - - if (key.equalsIgnoreCase (headerName)) { - return (String) headers.get(key); - } - } - - return null; } } 1.29 +18 -0 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.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- HTTPUtils.java 25 Jun 2002 21:23:53 -0000 1.28 +++ HTTPUtils.java 5 Sep 2002 16:50:52 -0000 1.29 @@ -132,6 +132,24 @@ } /** + * Obtain a header value from the table using a case insensitive search. + * + * @param headers a colletion of headers from the http response + * @param headerName the name of the header to find + * @return the header value or null if not found + */ + public static String getHeaderValue(Hashtable headers, + String headerName) { + for (Enumeration enum = headers.keys(); enum.hasMoreElements(); ) { + String key = (String) enum.nextElement(); + if (key.equalsIgnoreCase(headerName)) { + return (String) headers.get(key); + } + } + return null; + } + + /** * Utility function to determine port number from URL object. * * @param url URL object from which to determine port number
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>