org.apache.sling.jcr.classloader.internal.net

## Class JCRURLConnection

- java.lang.Object
- - java.net.URLConnection
  - - org.apache.sling.jcr.classloader.internal.net.JCRURLConnection

    public class JCRURLConnection
    extends URLConnection

The `JCRURLConnection` is the `URLConnection` implementation to access the data addressed by a JCR Repository URL.

As the primary use of a `URLConnection` and thus the `JCRURLConnection` is to provide access to the content of a resource identified by the URL, it is the primary task of this class to identify and access a repository `Property` based on the URL. This main task is executed in the `connect()` method.

Basically the guideposts to access content from a JCR Repository URL are the following:

- The URL must ultimately resolve to a repository property to provide content.
- If the URL itself is the path to a property, that property is used to provide the content.
- If the URL is a path to a node, either the `jcr:content/jcr:data` or `jcr:data` property is used or the primary item chain starting with this node is followed until no further primary items exist. If the final item is a property, that property is used to provide the content.
- If neither of the above methods resolve to a property, the `connect()` fails and access to the content is not possible.

A note on the `InputStream` available from `getInputStream()`: Unlike other implementations - for example for `file:` or `http:` URLs - which return the same stream on each call, this implementation returns a new stream on each invocation.

The following header fields are implemented by this class:

`Content-Length`
  The size of the content is filled from the `Property.getLength()` method, which returns the size in bytes of the property's value for binary values and the number of characters used for the string representation of the value for all other value types.
`Content-Type`
  The content type is retrieved from the `jcr:mimeType` property of the property's parent node if existing. Otherwise the `guessContentTypeFromName` method is called on the `path`. If this does not yield a content type, it is set to `application/octet-stream` for binary properties and to `text/plain` for other types.
`Content-Enconding`
  The content encoding is retrieved from the `jcr:econding` property of the property's parent node if existing. Otherwise this header field remains undefined (aka `null`).
`Last-Modified`
  The last modified type is retrieved from the `jcr:lastModified` property of the property's parent node if existing. Otherwise the last modification time is set to zero.

This class is not intended to be subclassed or instantiated by clients.

### Field Summary

### Fields inherited from class java.net.URLConnection

`allowUserInteraction, connected, doInput, doOutput, ifModifiedSince, url, useCaches`

### Method Summary

All Methods Instance Methods Concrete Methods
`void` `connect()` Connects to the URL setting the header fields and getting the contents.
`String` `getContentEncoding()` Returns the content encoding of the data as a string.
`int` `getContentLength()` Returns the content length of the data as an number.
`String` `getContentType()` Returns the content type of the data as a string.
`String` `getHeaderField(int i)` Get the header field with the given index.
`String` `getHeaderField(String s)` Gets the named header field.
`String` `getHeaderFieldKey(int i)` Get the name of the header field with the given index.
`Map<String,List<String>>` `getHeaderFields()` Returns an unmodifiable map of all header fields.
`InputStream` `getInputStream()` Returns an input stream that reads from this open connection.
`long` `getLastModified()` Returns the value of the `last-modified` header field.

### Methods inherited from class java.net.URLConnection

`addRequestProperty, getAllowUserInteraction, getConnectTimeout, getContent, getContent, getContentLengthLong, getDate, getDefaultAllowUserInteraction, getDefaultRequestProperty, getDefaultUseCaches, getDoInput, getDoOutput, getExpiration, getFileNameMap, getHeaderFieldDate, getHeaderFieldInt, getHeaderFieldLong, getIfModifiedSince, getOutputStream, getPermission, getReadTimeout, getRequestProperties, getRequestProperty, getURL, getUseCaches, guessContentTypeFromName, guessContentTypeFromStream, setAllowUserInteraction, setConnectTimeout, setContentHandlerFactory, setDefaultAllowUserInteraction, setDefaultRequestProperty, setDefaultUseCaches, setDoInput, setDoOutput, setFileNameMap, setIfModifiedSince, setReadTimeout, setRequestProperty, setUseCaches, toString`

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

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

### Method Detail

#### connect

    public void connect()
                 throws IOException

Connects to the URL setting the header fields and getting the contents.

The following algorithm is applied:

1. The repository item is retrieved from the URL's `URLHandler`.
2. If the item is a node, the `getPrimaryItem` method is called on that node. If the node has no primary item, the connection fails.
3. If the item - either from the handler or after calling `getPrimaryItem` is still a node, this method fails because a `Property` is required for a successfull connection.
4. If the property found above is a multi-valued property, connection fails, because multi-valued properties are not currently supported.
5. The content length header field is set from the property length (`Property.getLength())`).
6. The header fields for the content type, content encoding and last modification time are set from the `jcr:mimeType`, `jcr:encoding`, and `jcr:lastModification` properties of the property's parent node if existing. Otherwise the content encoding field is set to `null` and the last modification time is set to zero. The content type field is guessed from the name of the URL item. If the content type cannot be guessed, it is set to `application/octet-stream` if the property is of binary type or `text/plain` otherwise.

When this method successfully returns, this connection is considered connected. In case of an exception thrown, the connection is not connected.

Specified by:
  `connect` in class `URLConnection`
Throws:
  `IOException` - if an error occurrs retrieving the data property or any of the header field value properties or if any other errors occurrs. Any cuasing exception is set as the cause of this exception.

#### getInputStream

    public InputStream getInputStream()
                               throws IOException

Returns an input stream that reads from this open connection.

NOTES:

- Each call to this method returns a new `InputStream`.
- Do not forget to close the return stream when not used anymore for the system to be able to free resources.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getInputStream` in class `URLConnection`
Throws:
  `IOException` - if an error occurrs opening the connection through `connect()` or creating the `InputStream` on the repository `Property`.
See Also:
  `connect()`

#### getHeaderField

    public String getHeaderField(String s)

Gets the named header field. This implementation only supports the Content-Type, Content-Encoding, Content-Length and Last-Modified header fields. All other names return `null`.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getHeaderField` in class `URLConnection`
Parameters:
  `s` - The name of the header field value to return.
Returns:
  The corresponding value or `null` if not one of the supported fields or the named field's value cannot be retrieved from the data source.
See Also:
  `connect()`

#### getHeaderField

    public String getHeaderField(int i)

Get the header field with the given index. As with `getHeaderField(String)` only Content-Length, Content-Type, Content-Encoding, and Last-Modified are supported. All indexes other than 0, 1, 2 or 3 will return `null`.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getHeaderField` in class `URLConnection`
Parameters:
  `i` - The index of the header field value to return.
Returns:
  The corresponding value or `null` if not one of the supported fields or the known field's value cannot be retrieved from the data source.
See Also:
  `connect()`

#### getHeaderFieldKey

    public String getHeaderFieldKey(int i)

Get the name of the header field with the given index. As with `getHeaderField(String)` only Content-Length, Content-Type, Content-Encoding and Last-Modified are supported. All indexes other than 0, 1, 2 or 3 will return `null`.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getHeaderFieldKey` in class `URLConnection`
Parameters:
  `i` - The index of the header field name to return.
Returns:
  The corresponding name or `null` if not one of the supported fields.
See Also:
  `connect()`

#### getHeaderFields

    public Map<String,List<String>> getHeaderFields()

Returns an unmodifiable map of all header fields. Each entry is indexed with a string key naming the field. The entry's value is an unmodifiable list of the string values of the respective header field.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getHeaderFields` in class `URLConnection`
Returns:
  An unmodifiable map of header fields and their values. The map will be empty if an error occurrs connecting through `connect()`.
See Also:
  `connect()`

#### getContentType

    public String getContentType()

Returns the content type of the data as a string. This is just a perfomance convenience overwrite of the base class implementation.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getContentType` in class `URLConnection`
Returns:
  The content length of the data or `null` if the content type cannot be derived from the data source.
See Also:
  `connect()`

#### getContentEncoding

    public String getContentEncoding()

Returns the content encoding of the data as a string. This is just a perfomance convenience overwrite of the base class implementation.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getContentEncoding` in class `URLConnection`
Returns:
  The content encoding of the data or `null` if the content encoding cannot be derived from the data source.
See Also:
  `connect()`

#### getContentLength

    public int getContentLength()

Returns the content length of the data as an number. This is just a perfomance convenience overwrite of the base class implementation.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getContentLength` in class `URLConnection`
Returns:
  The content length of the data or -1 if the content length cannot be derived from the data source.
See Also:
  `connect()`

#### getLastModified

    public long getLastModified()

Returns the value of the `last-modified` header field. The result is the number of milliseconds since January 1, 1970 GMT.

Calling this method implicitly calls `connect()` to ensure the connection is open.

Overrides:
  `getLastModified` in class `URLConnection`
Returns:
  the date the resource referenced by this `URLConnection` was last modified, or -1 if not known.
See Also:
  `connect()`