<?xml version="1.0" encoding="UTF-8"?>
<!--
  _=_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_=
  Repose
  _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
  Copyright (C) 2010 - 2015 Rackspace US, Inc.
  _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
       http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  =_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_=_
  -->


<xs:schema xmlns:xerces="http://xerces.apache.org"
           xmlns:saxon="http://saxon.sf.net/"
           xmlns:html="http://www.w3.org/1999/xhtml"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://docs.openrepose.org/repose/http-connection-pool/v1.0"
           attributeFormDefault="unqualified"
           elementFormDefault="qualified"
           targetNamespace="http://docs.openrepose.org/repose/http-connection-pool/v1.0">

    <xs:element name="http-connection-pools" type="HttpConnectionPoolConfig"/>

    <!-- Type definitions -->
    <xs:simpleType name="PositiveInt">
        <xs:restriction base="xs:int">
            <xs:minInclusive value="0"/>
        </xs:restriction>
    </xs:simpleType>

    <xs:simpleType name="NegativeOneAndAllPositiveInt">
        <xs:restriction base="xs:int">
            <xs:minInclusive value="-1"/>
        </xs:restriction>
    </xs:simpleType>

    <xs:complexType name="HttpConnectionPoolConfig">
        <xs:annotation>
            <xs:documentation>
                <html:p>Connection Pool Management settings.</html:p>
                <html:p>
                    Please refer to
                    <html:a href="http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html">
                        Apache HttpComponents Connection Management
                    </html:a>
                </html:p>
            </xs:documentation>
        </xs:annotation>

        <xs:sequence>
            <xs:element name="pool" type="PoolType" minOccurs="1" maxOccurs="unbounded"/>
        </xs:sequence>

        <xs:assert vc:minVersion="1.1"
                   test="count(distinct-values(pool/@id)) = count(pool/@id)"
                   xerces:message="Pools must have unique ids"
                   saxon:message="Pools must have unique ids" xpathDefaultNamespace="##targetNamespace"/>

        <xs:assert vc:minVersion="1.1"
                   test="count(pool[xs:boolean(@default)=true()]) = 1"
                   xerces:message="One and only one default pool must be defined"
                   saxon:message="One and only one default pool must be defined"/>
    </xs:complexType>

    <xs:complexType name="PoolType">
        <xs:sequence>
            <xs:element type="headerListType" name="headers" minOccurs="0" maxOccurs="1"/>
        </xs:sequence>

        <xs:attribute name="http.conn-manager.max-total" type="PositiveInt" use="optional" default="400">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Connection Pool Management setting: max total concurrent connections that will be
                        created by a connection pool manager
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="http.conn-manager.max-per-route" type="PositiveInt" use="optional"
                      default="200">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Connection Pool Management setting: max total concurrent connections for a route
                        that will be created by a connection pool manager.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="http.socket.timeout" type="PositiveInt" use="optional" default="30000">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Defines the socket timeout (SO_TIMEOUT) in milliseconds, which is the timeout for
                        waiting for data or, put differently, a maximum period inactivity between two consecutive data
                        packets). A timeout value of zero is interpreted as an infinite timeout. This parameter expects
                        a value of type java.lang.Integer. If this parameter is not set, read operations will not
                        time out (infinite timeout).
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="http.socket.buffer-size" type="PositiveInt" use="optional" default="8192">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Determines the size of the internal socket buffer used to buffer data while
                        receiving / transmitting HTTP messages.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="http.connection.timeout" type="PositiveInt" use="optional" default="30000">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Determines the timeout in milliseconds until a connection is established. A
                        timeout value of zero is interpreted as an infinite timeout.
                        If this parameter is not set, connect operations will not time out (infinite timeout).
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="http.connection.max-line-length" type="PositiveInt" use="optional"
                      default="8192">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Determines the maximum line length limit. If set to a positive value, any HTTP
                        line exceeding this limit will cause an java.io.IOException. A zero value will
                        effectively disable the check and no limit will be enforced.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="http.connection.max-header-count" type="PositiveInt" use="optional"
                      default="100">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Determines the maximum HTTP header count allowed. If set to a positive value, the
                        number of HTTP headers received from the data stream exceeding this limit will cause an
                        java.io.IOException. A zero value will effectively disable the check and no limit will be
                        enforced.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="http.connection.max-status-line-garbage" type="PositiveInt" use="optional" default="100">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Defines the maximum number of ignorable lines before we expect a HTTP response's
                        status line. With HTTP/1.1 persistent connections, the problem arises that broken scripts could
                        return a wrong Content-Length (there are more bytes sent than specified). Unfortunately, in some
                        cases, this cannot be detected after the bad response, but only before the next one. So
                        HttpClient must be able to skip those surplus lines this way. 0 disallows all garbage/empty
                        lines before the status line. Use java.lang.Integer#MAX_VALUE for unlimited number.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="http.tcp.nodelay" type="xs:boolean" use="optional" default="true">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Determines whether Nagle's algorithm is to be used. Nagle's algorithm tries to
                        conserve bandwidth by minimizing the number of segments that are sent. When applications wish to
                        decrease network latency and increase performance, they can disable Nagle's algorithm (that is
                        enable TCP_NODELAY. Data will be sent earlier, at the cost of an increase in bandwidth
                        consumption. If this parameter is not set, TCP_NODELAY will be enabled (no delay).
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="keepalive.timeout" type="PositiveInt" use="optional" default="0">
            <xs:annotation>
                <xs:documentation>
                    <html:p>Some HTTP servers use a non-standard Keep-Alive header to communicate to the client the
                        period of time in seconds they intend to keep the connection alive on the server side. If this
                        header is present in the response, the value in this header will be used to determine the
                        maximum
                        length of time to keep a persistent connection open for.
                    </html:p>
                    <html:p>
                        If the Keep-Alive header is NOT present in the response, the value of keepalive.timeout is
                        evaluated. If this value is 0, the connection will be kept alive indefinitely. If the value is
                        greater than 0, the connection will be kept alive for the number of milliseconds specified.
                    </html:p>
                    <html:p>
                        Please refer to
                        <html:a href="http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html">Apache
                            HttpComponents Connection Management
                        </html:a>
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="id" type="xs:string" use="required">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Unique pool identifier.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="default" type="xs:boolean" use="optional" default="false">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Determines whether or not this pool configuration should
                        be considered the default when a pool of HTTP connections is requested from the service.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>

        <xs:attribute name="chunked-encoding" type="chunkedEncodingType" use="optional" default="true">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        Determines whether or not this client should send chunked data when forwarding requests to
                        the origin service.
                    </html:p>
                    <html:p>
                        If set to true or 1, chunked data will always be sent. Using the value 1 is considered
                        deprecated and will be removed in the next major release.
                        If set to false or 0, chunked data will never be sent. Using the value 0 is considered
                        deprecated and will be removed in the next major release.
                        If set to auto, chunked data will only be sent if the original request to Repose was chunked.
                        Note that the auto setting only has meaning for the default connection pool, as that is the only
                        pool that will be used to make requests to the origin service.
                    </html:p>
                    <html:p>
                        WARNING: Setting this attribute to false may cause repose to attempt to retrieve the
                        actual content length through reading the ServletInputStream. This will cause some performance
                        degradation as request body is no longer always streamed through.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="keystore-filename" type="xs:anyURI" use="optional">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        IF this attribute is configured,
                        THEN it is assumed that it points to the Java keystore containing the client certificate to
                        present for client authentication (e.g keystore.jks)
                        AND the keystore-password and key-password attributes are no longer optional.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="keystore-password" type="xs:string" use="optional">
            <xs:annotation>
                <xs:documentation>
                    <html:p>The password for the client authentication keystore.</html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="key-password" type="xs:string" use="optional">
            <xs:annotation>
                <xs:documentation>
                    <html:p>The password for the particular client authentication key in the keystore.</html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="truststore-filename" type="xs:anyURI" use="optional">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        The truststore used for validating the server this pool is connecting to.
                        This is typically set to the same path as the client authentication keystore.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="truststore-password" type="xs:string" use="optional">
            <xs:annotation>
                <xs:documentation>
                    <html:p>
                        The password for the client authentication truststore.
                        NOTE: This element is only used if the truststore-filename attribute is present.
                    </html:p>
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:assert vc:minVersion="1.1"
                   test="(@http.conn-manager.max-per-route) &lt;= (@http.conn-manager.max-total)"
                   xerces:message="Max connections per route must be less than or equal to total max connections"
                   saxon:message="Max connections per route must be less than or equal to total max connections"/>
        <xs:assert vc:minVersion="1.1"
                   test="if (@keystore-filename or @keystore-password or @key-password) then (@keystore-filename and @keystore-password and @key-password) else true()"
                   xerces:message="IF a keystore filename, password, or key password is provided, THEN all must be provided"
                   saxon:message="IF a keystore filename, password, or key password is provided, THEN all must be provided"/>
    </xs:complexType>

    <xs:complexType name="headerListType">
        <xs:annotation>
            <xs:documentation>
                <html:p>List of headers to add to each request made using this connection pool.</html:p>
            </xs:documentation>
        </xs:annotation>

        <xs:sequence>
            <xs:element type="headerType" name="header" minOccurs="1" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="headerType">
        <xs:annotation>
            <xs:documentation>
                <html:p>Header with a name and a value.</html:p>
            </xs:documentation>
        </xs:annotation>

        <xs:attribute name="name" type="xs:string" use="required"/>
        <xs:attribute name="value" type="xs:string" use="required"/>
    </xs:complexType>

    <xs:simpleType name="chunkedEncodingType">
        <xs:restriction base="xs:string">
            <xs:enumeration value="true"/>
            <xs:enumeration value="1"/>
            <xs:enumeration value="false"/>
            <xs:enumeration value="0"/>
            <xs:enumeration value="auto"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>
