Package org.acplt.oncrpc.web

# Class HttpClientConnection

java.lang.Object
org.acplt.oncrpc.web.HttpClientConnection

public class HttpClientConnection extends Object
The class `HttpClientConnection` provides a simple HTTP/1.1 compliant connection from a client to an HTTP server. This class does not provide a full-blown HTTP connection, but it is rather optimized for what ONC/RPC clients need in order to tunnel ONC remote procedure calls through ordinary HTTP connections, thus penetrating firewalls.

A `HttpClientConnection` is not that clever as you would first expect. Rather you have to do some things for yourself, like reconnecting dropped connections, and so on. While this sometimes result in more labour on the caller's shoulders, this keeps resource wasting at a minimum, and gives you full control over redirections and other mess -- you do want full control, right?.

For this reason, for instance, an `HttpClientConnection` does not buffer the whole request before sending it to the server but rather relies on the caller to supply the right content-length information. This avoids unnecessary double buffering but instead creates the bas64 encoded content on-the-fly.

Of course, this client connection object does not touch the content, it just suplies the pipe to swallow the data.

Version:
  $Revision: 1.1 $ $Date: 2003/08/13 12:03:45 $ $State: Exp $ $Locker: $
Author:
  Harald Albrecht

## Field Summary

Fields
Modifier and Type
Field
Description
`static final byte[]`
`CRLF`
`static final int`
`HTTP_DEFAULTPORT`
Default port where HTTP servers listen for incomming requests.

## Constructor Summary

Constructors
Constructor
Description
`HttpClientConnection(String hostname)`
Constructs a new `HttpClientConnection`.
`HttpClientConnection(String hostname, int port)`
Constructs a new `HttpClientConnection`.

## Method Summary

Modifier and Type
Method
Description
`int`
`beginDecoding()`
Begin receiving the content sent by the HTTP server.
`void`
`beginPostRequest(String path, String mimeType, int contentLength)`
Starts a new HTTP "POST" request and sends all necessary HTTP header fields.
`void`
`close()`
Closes the connection to the HTTP server and frees up some resources.
`void`
`endDecoding()`
This method silently discards any unread content, if the caller has yet not read all content.
`void`
`endPostRequest()`
Ends the HTTP "POST" request.
`String`
`getContentType()`
Returns the content type (MIME type, charset, etc.).
`boolean`
`getKeepAlive()`
`int`
`getRemainingContentLength()`
Returns amount of content still available (to be read).
`int`
`getResponseCode()`
Retrieve the response code of the last remote procedure call via HTTP.
`int`
`getTimeout()`
Retrieve the current timeout set for remote procedure calls.
`protected void`
`handleOption(String option, String value)`
Handle options sent by the HTTP server.
`int`
`readContentBytes(byte[] buffer, int offset, int length)`
Read content sent by the HTTP server.
`void`
`setTimeout(int milliseconds)`
Set the timout for sending or receiving information to/from the HTTP server.
`void`
`writeContentBytes(byte[] bytes, int offset, int length)`
Send (part) of the content to the HTTP server.

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

## Field Details

### HTTP_DEFAULTPORT

public static final int HTTP_DEFAULTPORT
Default port where HTTP servers listen for incomming requests. This is just a convenience definition to make the code more readable.

See Also:
  - Constant Field Values

### CRLF

public static final byte[] CRLF

## Constructor Details

### HttpClientConnection

public HttpClientConnection(String hostname)
Constructs a new `HttpClientConnection`. The port used on the HTTP server side is the default HTTP port, 80.

Parameters:
  `hostname` - name (DNS name or IP dotted address) of host running a HTTP server to which we want to connect to.

### HttpClientConnection

public HttpClientConnection(String hostname, int port)
Constructs a new `HttpClientConnection`.

Parameters:
  `hostname` - name (DNS name or IP dotted address) of host running a HTTP server to which we should connect to.
  `port` - Port number where the HTTP server can be contacted.

## Method Details

### close

public void close()
Closes the connection to the HTTP server and frees up some resources. After calling `close` it is still possible to open a new connection to the HTTP server once again.

### beginPostRequest

public void beginPostRequest(String path, String mimeType, int contentLength) throws IOException
Starts a new HTTP "POST" request and sends all necessary HTTP header fields. Next, the caller can send lots of content using the `writeContentBytes(byte[], int, int)` method. Finally, to finish the request he has to call the `endPostRequest()` method.

Parameters:
  `path` - Path to server object which handles the POST request. For instance, this can be a CGI script (although it better should not be one, except in the case of FAST CGI).
  `mimeType` - MIME-classified type of content to be sent.
  `contentLength` - Length of content to be sent. If negative, the length is not known in advance. In this case, keeping the connection alive is not possible, so callers should avoid this situation, if possible.
Throws:
  `IOException` - if an I/O exception occurs when sending the HTTP headers. In this case the connection is closed automatically and the caller must not send any content. However, the caller is free to give the request another try by calling `beginEncoding` again, thus opening a new HTTP connection.

### writeContentBytes

public void writeContentBytes(byte[] bytes, int offset, int length) throws IOException
Send (part) of the content to the HTTP server. Note that the output is done unbuffered, so callers should write their content in large chunks to avoid the calling overhead for sending data.

Parameters:
  `bytes` - The data.
  `offset` - Start offset in the data.
  `length` - Number of bytes to write.
Throws:
  `RuntimeException` - if too much content was sent.
  `IOException` - if an I/O error occurs.
  `NullPointerException` - if `bytes` is `null`.
  `IndexOutOfBoundsException` - if `offset` is negative, or `length` is negative, or `offset + length` is greater than the length of the array `bytes`.

### endPostRequest

public void endPostRequest() throws IOException
Ends the HTTP "POST" request. The next logical step for a caller is then to call ... #FIXME

Throws:
  `IOException` - The post data of the post request could not be flushed.

### handleOption

protected void handleOption(String option, String value)
Handle options sent by the HTTP server.

Currently the following options are handled by this class:

- Content-Length -- length of content following the header section
- Content-Type -- type of content sent
- Proxy-Connection -- handle keep-alive request
- Connection -- handle keep-alive request
- Transfer-Encoding -- transfer encoding choosen by HTTP server

Parameters:
  `option` - Name of option sent by HTTP server.
  `value` - Value of option.

### beginDecoding

public int beginDecoding() throws IOException
Begin receiving the content sent by the HTTP server. This method blocks until at least the HTTP header section has been received or until the connection times out.

Returns:
  HTTP server response code (status code).
Throws:
  `IOException` - Reading the HTTP header failed.

### getContentType

public String getContentType()
Returns the content type (MIME type, charset, etc.).

Returns:
  content type

### readContentBytes

public int readContentBytes(byte[] buffer, int offset, int length) throws IOException
Read content sent by the HTTP server. This method also handles the HTTP/1.1 chunked transfer encoding if the HTTP server insisted on using it. If only chunked transfer encoding has been introduced with the first official 0.9 protocol version of HTTP, it would have made sending ONC/RPC requests much easier, because we would not need to buffer the while request before sending it just to know its exact length. Unfortunately, chunking has only been introduced lately so we can not expect servers and especially proxies to handle it. Sigh.

Parameters:
  `buffer` - Buffer to receive the content sent by the HTTP server.
  `offset` - Start offset in the buffer.
  `length` - Number of bytes to receive.
Returns:
  The number of bytes in total read.
Throws:
  `ProtocolException` - if not enough content was available (the caller attempted to read more data than available) or if we received junk information violating the HTTP protocol specification.
  `IOException` - if an I/O error occurs.
  `NullPointerException` - if `bytes` is `null`.
  `IndexOutOfBoundsException` - if `offset` is negative, or `length` is negative, or `offset + length` is greater than the length of the array `bytes`.

### getRemainingContentLength

public int getRemainingContentLength()
Returns amount of content still available (to be read). This always shows the remaining amount and is updated whenever content is read using `readContentBytes(byte[], int, int)`.

Returns:
  Amount of content available.

### endDecoding

public void endDecoding() throws IOException

This method silently discards any unread content, if the caller has yet not read all content.

Throws:
  `IOException` - if reading remaining bytes fails.

### setTimeout

public void setTimeout(int milliseconds)
Set the timout for sending or receiving information to/from the HTTP server.

Parameters:
  `milliseconds` - Timeout in milliseconds.

### getTimeout

public int getTimeout()
Retrieve the current timeout set for remote procedure calls. A timeout of zero indicates batching calls (no reply message is expected).

Returns:
  Current timeout.

### getResponseCode

public int getResponseCode()
Retrieve the response code of the last remote procedure call via HTTP.

Returns:
  The numbver of the response code.

### getKeepAlive

public boolean getKeepAlive()

Returns:
  True if the keep alive flag is set, false otherwise.