/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2000-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine is distributed in the hope that it will *
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
* This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 *
* A copy of this license is located in file license.txt at the root of this *
* SDK or can be downloaded here: *
* http://www.gnu.org/licenses/lgpl-3.0.txt *
* *
*********************************************************************************/
package totalcross.xml.rpc;
import totalcross.io.ByteArrayStream;
import totalcross.io.IOException;
import totalcross.net.UnknownHostException;
import totalcross.sys.Convert;
import totalcross.sys.InvalidNumberException;
import totalcross.util.zip.ZLib;
/**
* @author pvanhout
*/
public class CompressedHttpClient extends StandardHttpClient
{
private static ByteArrayStream out = new ByteArrayStream(65500);
/**
* See the constructor for the StandardHttpClient
*/
public CompressedHttpClient(String hostname, int port, String uri, int openTimeout, int readTimeout, int writeTimeout) throws XmlRpcException, UnknownHostException
{
super(hostname, port, uri, openTimeout, readTimeout, writeTimeout);
}
public CompressedHttpClient(String hostname, int port, String uri) throws XmlRpcException, UnknownHostException
{
super(hostname, port, uri);
}
private Object readCompressedResponse(boolean asBytes) throws XmlRpcException, IOException
{
String v;
int contentLength=0;
if ((v=(String)htHeader.get("content-length")) != null)
try
{
contentLength = Convert.toInt(v);
}
catch (InvalidNumberException ine)
{
throw new XmlRpcException("Invalid response from server - No Content");
}
byte[] contentBuff = new byte[contentLength];
int contentRead = reader.readBytes(contentBuff, 0, contentLength);
if (contentRead != contentLength)
throw new XmlRpcException("Could not read answer: "+contentRead+" is less than "+contentLength);
ByteArrayStream is = new ByteArrayStream(contentBuff);
ByteArrayStream os = out;
os.reset();
int inflateSize = ZLib.inflate(is, os);
return asBytes ? (Object)os.toByteArray() : new String(os.getBuffer(), 0, inflateSize);
}
/**
* Executes a HTTP request to the connected server
*
* @param requestBody
* The contents of the HTTP request. Headers are added
* appropriately by this method after the request is compressed
* @throws XmlRpcException
* If the server returns a status code other than 200 OK
*/
public String execute(byte[] requestBody) throws XmlRpcException
{
return (String)privateExecute(requestBody, false);
}
/**
* Executes a HTTP request to the connected server
*
* @param requestBody
* The contents of the HTTP request. Headers are added
* appropriately by this method after the request is compressed
* @throws XmlRpcException
* If the server returns a status code other than 200 OK
*/
public byte[] executeReturnBytes(byte[] requestBody) throws XmlRpcException
{
return (byte[])privateExecute(requestBody, true);
}
private Object privateExecute(byte[] requestBody, boolean asBytes) throws XmlRpcException
{
try
{
// compress the body
ByteArrayStream is = new ByteArrayStream(requestBody);
ByteArrayStream os = out;
out.reset();
int compressedSize = ZLib.deflate(is, os, ZLib.BEST_COMPRESSION);
// send to the server
writeRequest(os.getBuffer(), compressedSize);
checkResponse();
parseHeader();
// read the answer
boolean inflateResults = "deflate".equals(htHeader.get("content-encoding"));
return inflateResults ? readCompressedResponse(asBytes) : asBytes ? readResponseBytes() : readResponse();
}
catch (IOException e)
{
throw new XmlRpcException(e.getMessage());
}
}
/** Writes the headers for a HTTP request, adding the deflate method as content-encoding. */
protected StringBuffer writeRequestHeader(int requestLength)
{
StringBuffer requestHeader = super.writeRequestHeader(requestLength);
requestHeader.append("Content-Encoding: deflate\r\n"); // append our specific header
return requestHeader;
}
}