text:
/*
 * based on mod_tls.c - Apache SSL/TLS module for NetWare by Mike Gardiner.
 *
 * This module gives Apache the ability to do SSL/TLS with a minimum amount
 * of effort.  All of the SSL/TLS logic is already on NetWare versions 5 and
 * above and is interfaced through WinSock on NetWare.  As you can see in
 * the code below SSL/TLS sockets can be created with three WinSock calls.
 *
 * To load, simply place the module in the modules directory under the main
 * apache tree.  Then add a "SecureListen" with two arguments.  The first
 * argument is an address and/or port.  The second argument is the key pair
 * name as created in ConsoleOne.
 *
 *  Examples:
 *
 *          SecureListen 443 "SSL CertificateIP"
 *          SecureListen 123.45.67.89:443 mycert
 *
 * The module also supports RFC 2817 / TLS Upgrade for HTTP 1.1.
 * For this add a "NWSSLUpgradeable" with two arguments.  The first
 * argument is an address and/or port.  The second argument is the key pair
 * name as created in ConsoleOne.
 *
 *  Examples:
 *
 *          NWSSLUpgradeable 8080 "SSL CertificateIP"
 *          NWSSLUpgradeable 123.45.67.89:8080 mycert
 *
 */

#define WS_SSL

#define  MAX_ADDRESS  512
#define  MAX_KEY       80

#include "httpd.h"
#include "http_config.h"
#include "http_connection.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
#include "ap_listen.h"
#include "apr_strings.h"
#include "apr_portable.h"
#include "apr_optional.h"

#include <unilib.h>

#ifndef SO_TLS_UNCLEAN_SHUTDOWN
#define SO_TLS_UNCLEAN_SHUTDOWN 0
#endif

/* The ssl_var_lookup() optional function retrieves SSL environment
 * variables. */
APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup,
                        (apr_pool_t *, server_rec *,
                         conn_rec *, request_rec *,
                         char *));

/* An optional function which returns non-zero if the given connection
 * is using SSL/TLS. */
APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));

/* The ssl_proxy_enable() and ssl_engine_disable() optional functions
 * are used by mod_proxy to enable use of SSL for outgoing
 * connections. */
APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));

#define strEQ(s1,s2)     (strcmp(s1,s2)        == 0)
#define strNE(s1,s2)     (strcmp(s1,s2)        != 0)
#define strEQn(s1,s2,n)  (strncmp(s1,s2,n)     == 0)
#define strNEn(s1,s2,n)  (strncmp(s1,s2,n)     != 0)

#define strcEQ(s1,s2)    (strcasecmp(s1,s2)    == 0)
#define strcNE(s1,s2)    (strcasecmp(s1,s2)    != 0)
#define strcEQn(s1,s2,n) (strncasecmp(s1,s2,n) == 0)
#define strcNEn(s1,s2,n) (strncasecmp(s1,s2,n) != 0)

#define strIsEmpty(s)    (s == NULL || s[0] == NUL)

module AP_MODULE_DECLARE_DATA nwssl_module;

typedef struct NWSSLSrvConfigRec NWSSLSrvConfigRec;
typedef struct seclisten_rec seclisten_rec;
typedef struct seclistenup_rec seclistenup_rec;
typedef struct secsocket_data secsocket_data;

struct seclisten_rec {
    seclisten_rec *next;
    struct sockaddr_in local_addr;   /* local IP address and port */
    int fd;
    int used;                        /* Only used during restart */
    char key[MAX_KEY];
    int mutual;
    char *addr;
    apr_port_t port;
};

struct seclistenup_rec {
    seclistenup_rec *next;
    char key[MAX_KEY];
    char *addr;
    apr_port_t port;
};

struct NWSSLSrvConfigRec {
    apr_table_t *sltable;
    apr_table_t *slutable;
    apr_pool_t *pPool;
};

struct secsocket_data {
    apr_socket_t* csd;
    int is_secure;
};

static apr_array_header_t *certlist = NULL;
static unicode_t** certarray = NULL;
static int numcerts = 0;
static seclisten_rec* ap_seclisteners = NULL;
static seclistenup_rec* ap_seclistenersup = NULL;

static ap_listen_rec *nw_old_listeners;

#define get_nwssl_cfg(srv) (NWSSLSrvConfigRec *) ap_get_module_config(srv->module_config, &nwssl_module)

static void build_cert_list(apr_pool_t *p)
{
    int i;
    char **rootcerts = (char **)certlist->elts;

    numcerts = certlist->nelts;
    certarray = apr_palloc(p, sizeof(unicode_t*)*numcerts);

    for (i = 0; i < numcerts; ++i) {
        unicode_t *unistr;
        unistr = (unicode_t*)apr_palloc(p, strlen(rootcerts[i])*4);
        loc2uni (UNI_LOCAL_DEFAULT, unistr, rootcerts[i], 0, 2);
        certarray[i] = unistr;
    }
}

/*
 * Parses a host of the form <address>[:port]
 * :port is permitted if 'port' is not NULL
 */
static unsigned long parse_addr(const char *w, unsigned short *ports)
{
    struct hostent *hep;
    unsigned long my_addr;
    char *p;

    p = strchr(w, ':');
    if (ports != NULL) {
        *ports = 0;
        if (p != NULL && strcmp(p + 1, "*") != 0)
            *ports = atoi(p + 1);
    }

    if (p != NULL)
        *p = '\0';
    if (strcmp(w, "*") == 0) {
        if (p != NULL)
            *p = ':';
        return htonl(INADDR_ANY);
    }

    my_addr = apr_inet_addr((char *)w);
    if (my_addr != INADDR_NONE) {
        if (p != NULL)
            *p = ':';
        return my_addr;
    }

    hep = gethostbyname(w);

    if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
        /* XXX Should be echoing by h_errno the actual failure, no?
         * ap_log_error would be good here.  Better yet - APRize.
         */
        fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w);
        exit(1);
    }

    if (hep->h_addr_list[1]) {
        fprintf(stderr, "Host %s has multiple addresses ---\n", w);
        fprintf(stderr, "you must choose one explicitly for use as\n");
        fprintf(stderr, "a secure port.  Exiting!!!\n");
        exit(1);
    }

    if (p != NULL)
        *p = ':';

    return ((struct in_addr *) (hep->h_addr))->s_addr;
}

static int find_secure_listener(seclisten_rec *lr)
{
    seclisten_rec *sl;

    for (sl = ap_seclisteners; sl; sl = sl->next) {
        if (!memcmp(&sl->local_addr, &lr->local_addr, sizeof(sl->local_addr))) {
            sl->used = 1;
            return sl->fd;
        }
    }
    return -1;
}

static char *get_port_key(conn_rec *c)
{
    seclistenup_rec *sl;

    for (sl = ap_seclistenersup; sl; sl = sl->next) {
        if ((sl->port == (c->local_addr)->port) &&
            ((strcmp(sl->addr, "0.0.0.0") == 0) ||
            (strcmp(sl->addr, c->local_ip) == 0))) {
            return sl->key;
        }
    }
    return NULL;
}

static int make_secure_socket(apr_pool_t *pconf,
                              const struct sockaddr_in *server,
                              char* key, int mutual, server_rec *sconf)
{
    int s;
    char addr[MAX_ADDRESS];
    struct sslserveropts opts;
    unsigned int optParam;
    WSAPROTOCOL_INFO SecureProtoInfo;

    if (server->sin_addr.s_addr != htonl(INADDR_ANY))
        apr_snprintf(addr, sizeof(addr), "address %s port %d",
            inet_ntoa(server->sin_addr), ntohs(server->sin_port));
    else
        apr_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));

    /* note that because we're about to slack we don't use psocket */
    memset(&SecureProtoInfo, 0, sizeof(WSAPROTOCOL_INFO));

    SecureProtoInfo.iAddressFamily = AF_INET;
    SecureProtoInfo.iSocketType = SOCK_STREAM;
    SecureProtoInfo.iProtocol = IPPROTO_TCP;
    SecureProtoInfo.iSecurityScheme = SECURITY_PROTOCOL_SSL;

    s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,
                  (LPWSAPROTOCOL_INFO)&SecureProtoInfo, 0, 0);

    if (s == INVALID_SOCKET) {
        ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
                     APLOGNO(02120)
                     "make_secure_socket: failed to get a socket for %s",
                     addr);
        return -1;
    }

    if (!mutual) {
        optParam = SO_SSL_ENABLE | SO_SSL_SERVER;

        if (WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam,
            sizeof(optParam), NULL, 0, NULL, NULL, NULL)) {
            ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
                         APLOGNO(02121)
                         "make_secure_socket: for %s, WSAIoctl: "
                         "(SO_SSL_SET_FLAGS)", addr);
            return -1;
        }
    }

    opts.cert = key;
    opts.certlen = strlen(key);
    opts.sidtimeout = 0;
    opts.sidentries = 0;
    opts.siddir = NULL;

    if (WSAIoctl(s, SO_SSL_SET_SERVER, (char *)&opts, sizeof(opts),
                 NULL, 0, NULL, NULL, NULL) != 0) {
        ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
                     APLOGNO(02122)
                     "make_secure_socket: for %s, WSAIoctl: "
                     "(SO_SSL_SET_SERVER)", addr);
        return -1;
    }

    if (mutual) {
        optParam = 0x07;  /* SO_SSL_AUTH_CLIENT */

        if (WSAIoctl(s, SO_SSL_SET_FLAGS, (char*)&optParam, sizeof(optParam),
                     NULL, 0, NULL, NULL, NULL)) {
            ap_log_error(APLOG_MARK, APLOG_CRIT, WSAGetLastError(), sconf,
                         APLOGNO(02123)
                         "make_secure_socket: for %s, WSAIoctl: "
                         "(SO_SSL_SET_FLAGS)", addr);
            return -1;
        }
    }

    optParam = SO_TLS_UNCLEAN_SHUTDOWN;
    WSAIoctl(s, SO_SSL_SET_FLAGS, (char *)&optParam, sizeof(optParam),
             NULL, 0, NULL, NULL, NULL);

    return s;
}

static int convert_secure_socket(conn_rec *c, apr_socket_t *csd)
{
    int rcode;
    struct tlsclientopts sWS2Opts;
    struct nwtlsopts sNWTLSOpts;
    struct sslserveropts opts;
    unsigned long ulFlags;
    SOCKET sock;
    unicode_t keyFileName[60];

    apr_os_sock_get(&sock, csd);

    /* zero out buffers */
    memset((char *)&sWS2Opts, 0, sizeof(struct tlsclientopts));
    memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));

    /* turn on ssl for the socket */
    ulFlags = (numcerts ? SO_TLS_ENABLE : SO_TLS_ENABLE | SO_TLS_BLIND_ACCEPT);
    rcode = WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long),
                     NULL, 0, NULL, NULL, NULL);
    if (SOCKET_ERROR == rcode) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server, APLOGNO(02124)
                     "Error: %d with WSAIoctl(flag SO_TLS_ENABLE)",
                     WSAGetLastError());
        return rcode;
    }

    ulFlags = SO_TLS_UNCLEAN_SHUTDOWN;
    WSAIoctl(sock, SO_TLS_SET_FLAGS, &ulFlags, sizeof(unsigned long),
             NULL, 0, NULL, NULL, NULL);

    /* setup the socket for SSL */
    memset (&sWS2Opts, 0, sizeof(sWS2Opts));
    memset (&sNWTLSOpts, 0, sizeof(sNWTLSOpts));
    sWS2Opts.options = &sNWTLSOpts;

    if (numcerts) {
        sNWTLSOpts.walletProvider = WAL_PROV_DER;   /* the wallet provider defined in wdefs.h */
        sNWTLSOpts.TrustedRootList = certarray;     /* array of certs in UNICODE format       */
        sNWTLSOpts.numElementsInTRList = numcerts;  /* number of certs in TRList              */
    }
    else {
        /* setup the socket for SSL */
        unicpy(keyFileName, L"SSL CertificateIP");
        sWS2Opts.wallet = keyFileName;              /* no client certificate */
        sWS2Opts.walletlen = unilen(keyFileName);

        sNWTLSOpts.walletProvider = WAL_PROV_KMO;   /* the wallet provider defined in wdefs.h */
    }

    /* make the IOCTL call */
    rcode = WSAIoctl(sock, SO_TLS_SET_CLIENT, &sWS2Opts,
                     sizeof(struct tlsclientopts), NULL, 0, NULL,
                     NULL, NULL);

    /* make sure that it was successful */
    if (SOCKET_ERROR == rcode ) {
    ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server, APLOGNO(02125)
                 "Error: %d with WSAIoctl(SO_TLS_SET_CLIENT)",
                 WSAGetLastError());
    }
    return rcode;
}

static int SSLize_Socket(SOCKET socketHnd, char *key, request_rec *r)
{
    int rcode;
    struct tlsserveropts sWS2Opts;
    struct nwtlsopts    sNWTLSOpts;
    unicode_t SASKey[512];
    unsigned long ulFlag;

    memset((char *)&sWS2Opts, 0, sizeof(struct tlsserveropts));
    memset((char *)&sNWTLSOpts, 0, sizeof(struct nwtlsopts));

    ulFlag = SO_TLS_ENABLE;
    rcode = WSAIoctl(socketHnd, SO_TLS_SET_FLAGS, &ulFlag,
                     sizeof(unsigned long), NULL, 0, NULL, NULL, NULL);
    if(rcode) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02126)
                     "Error: %d with WSAIoctl(SO_TLS_SET_FLAGS, SO_TLS_ENABLE)",
                     WSAGetLastError());
        goto ERR;
    }

    ulFlag = SO_TLS_SERVER;
    rcode = WSAIoctl(socketHnd, SO_TLS_SET_FLAGS, &ulFlag,
                     sizeof(unsigned long),NULL, 0, NULL, NULL, NULL);

    if (rcode) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02127)
                     "Error: %d with WSAIoctl(SO_TLS_SET_FLAGS, SO_TLS_SERVER)",
                     WSAGetLastError());
        goto ERR;
    }

    loc2uni(UNI_LOCAL_DEFAULT, SASKey, key, 0, 0);

    /* setup the tlsserveropts struct */
    sWS2Opts.wallet = SASKey;
    sWS2Opts.walletlen = unilen(SASKey);
    sWS2Opts.sidtimeout = 0;
    sWS2Opts.sidentries = 0;
    sWS2Opts.siddir = NULL;
    sWS2Opts.options = &sNWTLSOpts;

    /* setup the nwtlsopts structure */

    sNWTLSOpts.walletProvider               = WAL_PROV_KMO;
    sNWTLSOpts.keysList                     = NULL;
    sNWTLSOpts.numElementsInKeyList         = 0;
    sNWTLSOpts.reservedforfutureuse         = NULL;
    sNWTLSOpts.reservedforfutureCRL         = NULL;
    sNWTLSOpts.reservedforfutureCRLLen      = 0;
    sNWTLSOpts.reserved1                    = NULL;
    sNWTLSOpts.reserved2                    = NULL;
    sNWTLSOpts.reserved3                    = NULL;

    rcode = WSAIoctl(socketHnd,
                     SO_TLS_SET_SERVER,
                     &sWS2Opts,
                     sizeof(struct tlsserveropts),
                     NULL,
                     0,
                     NULL,
                     NULL,
                     NULL);
    if (SOCKET_ERROR == rcode) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02128)
                     "Error: %d with WSAIoctl(SO_TLS_SET_SERVER)", WSAGetLastError());
        goto ERR;
    }

ERR:
    return rcode;
}

static const char *set_secure_listener(cmd_parms *cmd, void *dummy,
                                       const char *ips, const char* key,
                                       const char* mutual)
{
    NWSSLSrvConfigRec* sc = get_nwssl_cfg(cmd->server);
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    char *ports, *addr;
    unsigned short port;
    seclisten_rec *new;
    ap_listen_rec **walk;
    apr_sockaddr_t *sa;
    int found_listener = 0;

    if (err != NULL)
        return err;

    ports = strchr(ips, ':');

    if (ports != NULL) {
        if (ports == ips)
            return "Missing IP address";
        else if (ports[1] == '\0')
            return "Address must end in :<port-number>";

        *(ports++) = '\0';
    }
    else {
        ports = (char*)ips;
    }

    new = apr_pcalloc(cmd->server->process->pool, sizeof(seclisten_rec));
    new->local_addr.sin_family = AF_INET;

    if (ports == ips) {
        new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        addr = apr_pstrdup(cmd->server->process->pool, "0.0.0.0");
    }
    else {
        new->local_addr.sin_addr.s_addr = parse_addr(ips, NULL);
        addr = apr_pstrdup(cmd->server->process->pool, ips);
    }

    port = atoi(ports);

    if (!port)
        return "Port must be numeric";

    /* If the specified addr:port was created previously, put the listen
       socket record back on the ap_listeners list so that the socket
       will be reused rather than recreated */
    for (walk = &nw_old_listeners; *walk;) {
        sa = (*walk)->bind_addr;
        if (sa) {
            ap_listen_rec *new;
            apr_port_t oldport;

            oldport = sa->port;
            /* If both ports are equivalent, then if their names are equivalent,
             * then we will re-use the existing record.
             */
            if (port == oldport &&
                ((!addr && !sa->hostname) ||
                 ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) {
                new = *walk;
                *walk = new->next;
                new->next = ap_listeners;
                ap_listeners = new;
                found_listener = 1;
                continue;
            }
        }

        walk = &(*walk)->next;
    }

    apr_table_add(sc->sltable, ports, addr);

    /* If we found a pre-existing listen socket record, then there
       is no need to create a new secure listen socket record. */
    if (found_listener) {
        return NULL;
    }

    new->local_addr.sin_port = htons(port);
    new->fd = -1;
    new->used = 0;
    new->next = ap_seclisteners;
    strcpy(new->key, key);
    new->mutual = (mutual) ? 1 : 0;
    new->addr = addr;
    new->port = port;
    ap_seclisteners = new;
    return NULL;
}

static const char *set_secure_upgradeable_listener(cmd_parms *cmd, void *dummy,
                                       const char *ips, const char* key)
{
    NWSSLSrvConfigRec* sc = get_nwssl_cfg(cmd->server);
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    char *ports, *addr;
    unsigned short port;
    seclistenup_rec *new;

    if (err != NULL)
        return err;

    ports = strchr(ips, ':');

    if (ports != NULL) {
        if (ports == ips)
            return "Missing IP address";
        else if (ports[1] == '\0')
            return "Address must end in :<port-number>";

        *(ports++) = '\0';
    }
    else {
        ports = (char*)ips;
    }

    if (ports == ips) {
        addr = apr_pstrdup(cmd->pool, "0.0.0.0");
    }
    else {
        addr = apr_pstrdup(cmd->pool, ips);
    }

    port = atoi(ports);

    if (!port)
        return "Port must be numeric";

    apr_table_set(sc->slutable, ports, addr);

    new = apr_pcalloc(cmd->pool, sizeof(seclistenup_rec));
    new->next = ap_seclistenersup;
    strcpy(new->key, key);
    new->addr = addr;
    new->port = port;
    ap_seclistenersup = new;

    return err;
}

static apr_status_t nwssl_socket_cleanup(void *data)
{
    ap_listen_rec* slr = (ap_listen_rec*)data;
    ap_listen_rec* lr;

    /* Remove our secure listener from the listener list */
    for (lr = ap_listeners; lr; lr = lr->next) {
        /* slr is at the head of the list */
        if (lr == slr) {
            ap_listeners = slr->next;
            break;
        }
        /* slr is somewhere in between or at the end*/
        if (lr->next == slr) {
            lr->next = slr->next;
            break;
        }
    }
    return APR_SUCCESS;
}

static const char *set_trusted_certs(cmd_parms *cmd, void *dummy, char *arg)
{
    char **ptr = (char **)apr_array_push(certlist);

    *ptr = apr_pstrdup(cmd->pool, arg);
    return NULL;
}

static int nwssl_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
                         apr_pool_t *ptemp)
{
    seclisten_rec* ap_old_seclisteners;
    ap_listen_rec **walk;
    seclisten_rec **secwalk;
    apr_sockaddr_t *sa;
    int found;

    /* Pull all of the listeners that were created by mod_nw_ssl out of the
       ap_listeners list so that the normal listen socket processing does
       automatically close them */
    nw_old_listeners = NULL;
    ap_old_seclisteners = NULL;

    for (secwalk = &ap_seclisteners; *secwalk;) {
        found = 0;
        for (walk = &ap_listeners; *walk;) {
            sa = (*walk)->bind_addr;
            if (sa) {
                ap_listen_rec *new;
                seclisten_rec *secnew;
                apr_port_t oldport;

                oldport = sa->port;
                /* If both ports are equivalent, then if their names are equivalent,
                 * then we will re-use the existing record.
                 */
                if ((*secwalk)->port == oldport &&
                    ((!(*secwalk)->addr && !sa->hostname) ||
                     (((*secwalk)->addr && sa->hostname) && !strcmp(sa->hostname, (*secwalk)->addr)))) {
                    /* Move the listen socket from ap_listeners to nw_old_listeners */
                    new = *walk;
                    *walk = new->next;
                    new->next = nw_old_listeners;
                    nw_old_listeners = new;

                    /* Move the secure socket record to ap_old_seclisterners */
                    secnew = *secwalk;
                    *secwalk = secnew->next;
                    secnew->next = ap_old_seclisteners;
                    ap_old_seclisteners = secnew;
                    found = 1;
                    break;
                }
            }

            walk = &(*walk)->next;
        }
        if (!found && &(*secwalk)->next) {
            secwalk = &(*secwalk)->next;
        }
    }

    /* Restore the secure socket records list so that the post config can
       process all of the sockets normally */
    ap_seclisteners = ap_old_seclisteners;
    ap_seclistenersup = NULL;
    certlist = apr_array_make(pconf, 1, sizeof(char *));

    /* Now that we have removed all of the mod_nw_ssl created socket records,
       allow the normal listen socket handling to occur.
       NOTE: If for any reason mod_nw_ssl is removed as a built-in module,
       the following call must be put back into the pre-config handler of the
       MPM.  It is only here to ensure that mod_nw_ssl fixes up the listen
       socket list before anything else looks at it. */
    ap_listen_pre_config();

    return OK;
}

static int nwssl_pre_connection(conn_rec *c, void *csd)
{

    if (apr_table_get(c->notes, "nwconv-ssl")) {
        convert_secure_socket(c, (apr_socket_t*)csd);
    }
    else {
        secsocket_data *csd_data = apr_palloc(c->pool, sizeof(secsocket_data));

        csd_data->csd = (apr_socket_t*)csd;
        csd_data->is_secure = 0;
        ap_set_module_config(c->conn_config, &nwssl_module, (void*)csd_data);
    }

    return OK;
}

static int nwssl_post_config(apr_pool_t *pconf, apr_pool_t *plog,
                          apr_pool_t *ptemp, server_rec *s)
{
    seclisten_rec* sl;
    ap_listen_rec* lr;
    apr_socket_t*  sd;
    apr_status_t status;
    seclistenup_rec *slu;
    int found;
    ap_listen_rec *walk;
    seclisten_rec *secwalk, *lastsecwalk;
    apr_sockaddr_t *sa;

    /* Walk the old listeners list and compare it to the secure
       listeners list and remove any secure listener records that
       are not being reused */
    for (walk = nw_old_listeners; walk; walk = walk->next) {
        sa = walk->bind_addr;
        if (sa) {
            ap_listen_rec *new;
            apr_port_t oldport;

            oldport = sa->port;
            for (secwalk = ap_seclisteners, lastsecwalk = ap_seclisteners; secwalk; secwalk = lastsecwalk->next) {
                unsigned short port = secwalk->port;
                char *addr = secwalk->addr;
                /* If both ports are equivalent, then if their names are equivalent,
                 * then we will re-use the existing record.
                 */
                if (port == oldport &&
                    ((!addr && !sa->hostname) ||
                     ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) {
                    if (secwalk == ap_seclisteners) {
                        ap_seclisteners = secwalk->next;
                    }
                    else {
                        lastsecwalk->next = secwalk->next;
                    }
                    apr_socket_close(walk->sd);
                    walk->active = 0;
                    break;
                }
                else {
                    lastsecwalk = secwalk;
                }
            }
        }
    }

    for (sl = ap_seclisteners; sl != NULL; sl = sl->next) {
        /* If we find a pre-existing listen socket and it has already been
           created, then no neeed to go any further, just reuse it. */
        if (((sl->fd = find_secure_listener(sl)) >= 0) && (sl->used)) {
            continue;
        }

        if (sl->fd < 0)
            sl->fd = make_secure_socket(s->process->pool, &sl->local_addr, sl->key, sl->mutual, s);

        if (sl->fd >= 0) {
            apr_os_sock_info_t sock_info;

            sock_info.os_sock = &(sl->fd);
            sock_info.local = (struct sockaddr*)&(sl->local_addr);
            sock_info.remote = NULL;
            sock_info.family = APR_INET;
            sock_info.type = SOCK_STREAM;

            apr_os_sock_make(&sd, &sock_info, s->process->pool);

            lr = apr_pcalloc(s->process->pool, sizeof(ap_listen_rec));

            if (lr) {
                lr->sd = sd;
                if ((status = apr_sockaddr_info_get(&lr->bind_addr, sl->addr, APR_UNSPEC, sl->port, 0,
                                              s->process->pool)) != APR_SUCCESS) {
                    ap_log_perror(APLOG_MARK, APLOG_CRIT, status, pconf, APLOGNO(02129)
                                 "alloc_listener: failed to set up sockaddr for %s:%d", sl->addr, sl->port);
                    return HTTP_INTERNAL_SERVER_ERROR;
                }
                lr->next = ap_listeners;
                ap_listeners = lr;
                apr_pool_cleanup_register(s->process->pool, lr, nwssl_socket_cleanup, apr_pool_cleanup_null);
            }
        } else {
            return HTTP_INTERNAL_SERVER_ERROR;
        }
    }

    for (slu = ap_seclistenersup; slu; slu = slu->next) {
        /* Check the listener list for a matching upgradeable listener */
        found = 0;
        for (lr = ap_listeners; lr; lr = lr->next) {
            if (slu->port == lr->bind_addr->port) {
                found = 1;
                break;
            }
        }
        if (!found) {
            ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, plog, APLOGNO(02130)
                         "No Listen directive found for upgradeable listener %s:%d", slu->addr, slu->port);
        }
    }

    build_cert_list(s->process->pool);

    return OK;
}

static void *nwssl_config_server_create(apr_pool_t *p, server_rec *s)
{
    NWSSLSrvConfigRec *new = apr_palloc(p, sizeof(NWSSLSrvConfigRec));
    new->sltable = apr_table_make(p, 5);
    new->slutable = apr_table_make(p, 5);
    return new;
}

static void *nwssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
{
    NWSSLSrvConfigRec *base = (NWSSLSrvConfigRec *)basev;
    NWSSLSrvConfigRec *add  = (NWSSLSrvConfigRec *)addv;
    NWSSLSrvConfigRec *merged  = (NWSSLSrvConfigRec *)apr_palloc(p, sizeof(NWSSLSrvConfigRec));
    return merged;
}

static int compare_ipports(void *rec, const char *key, const char *value)
{
    conn_rec *c = (conn_rec*)rec;

    if (value &&
        ((strcmp(value, "0.0.0.0") == 0) || (strcmp(value, c->local_ip) == 0)))
    {
        return 0;
    }
    return 1;
}

static int isSecureConnEx (const server_rec *s, const conn_rec *c, const apr_table_t *t)
{
    char port[8];

    itoa((c->local_addr)->port, port, 10);
    if (!apr_table_do(compare_ipports, (void*)c, t, port, NULL)) {
        return 1;
    }

    return 0;
}

static int isSecureConn (const server_rec *s, const conn_rec *c)
{
    NWSSLSrvConfigRec *sc = get_nwssl_cfg(s);

    return isSecureConnEx (s, c, sc->sltable);
}

static int isSecureConnUpgradeable (const server_rec *s, const conn_rec *c)
{
    NWSSLSrvConfigRec *sc = get_nwssl_cfg(s);

    return isSecureConnEx (s, c, sc->slutable);
}

static int isSecure (const request_rec *r)
{
    return isSecureConn (r->server, r->connection);
}

static int isSecureUpgradeable (const request_rec *r)
{
    return isSecureConnUpgradeable (r->server, r->connection);
}

static int isSecureUpgraded (const request_rec *r)
{
    secsocket_data *csd_data = (secsocket_data*)ap_get_module_config(r->connection->conn_config, &nwssl_module);

    return csd_data->is_secure;
}

static int nwssl_hook_Fixup(request_rec *r)
{
    if (!isSecure(r) && !isSecureUpgraded(r))
        return DECLINED;

    apr_table_setn(r->subprocess_env, "HTTPS", "on");

    return DECLINED;
}

static const char *nwssl_hook_http_scheme(const request_rec *r)
{
    if (isSecure(r) && !isSecureUpgraded(r))
        return "https";

    return NULL;
}

static apr_port_t nwssl_hook_default_port(const request_rec *r)
{
    if (isSecure(r))
        return DEFAULT_HTTPS_PORT;

    return 0;
}

int ssl_proxy_enable(conn_rec *c)
{
    apr_table_setn(c->notes, "nwconv-ssl", "Y");

    return 1;
}

int ssl_engine_disable(conn_rec *c)
{
    return 1;
}

static int ssl_is_https(conn_rec *c)
{
    secsocket_data *csd_data = (secsocket_data*)ap_get_module_config(c->conn_config, &nwssl_module);

    return isSecureConn (c->base_server, c) || (csd_data && csd_data->is_secure);
}

/* This function must remain safe to use for a non-SSL connection. */
char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, char *var)
{
    NWSSLSrvConfigRec *mc = get_nwssl_cfg(s);
    const char *result;
    BOOL resdup;
    apr_time_exp_t tm;

    result = NULL;
    resdup = TRUE;

    /*
     * When no pool is given try to find one
     */
    if (p == NULL) {
        if (r != NULL)
            p = r->pool;
        else if (c != NULL)
            p = c->pool;
        else
            p = mc->pPool;
    }

    /*
     * Request dependent stuff
     */
    if (r != NULL) {
        switch (var[0]) {
        case 'H':
        case 'h':
            if (strcEQ(var, "HTTP_USER_AGENT"))
                result = apr_table_get(r->headers_in, "User-Agent");
            else if (strcEQ(var, "HTTP_REFERER"))
                result = apr_table_get(r->headers_in, "Referer");
            else if (strcEQ(var, "HTTP_COOKIE"))
                result = apr_table_get(r->headers_in, "Cookie");
            else if (strcEQ(var, "HTTP_FORWARDED"))
                result = apr_table_get(r->headers_in, "Forwarded");
            else if (strcEQ(var, "HTTP_HOST"))
                result = apr_table_get(r->headers_in, "Host");
            else if (strcEQ(var, "HTTP_PROXY_CONNECTION"))
                result = apr_table_get(r->headers_in, "Proxy-Connection");
            else if (strcEQ(var, "HTTP_ACCEPT"))
                result = apr_table_get(r->headers_in, "Accept");
            else if (strcEQ(var, "HTTPS")) {
                if (isSecure(r) || isSecureUpgraded(r))
                    result = "on";
                else
                    result = "off";
            }
            else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5))
                /* all other headers from which we are still not know about */
                result = apr_table_get(r->headers_in, var+5);
            break;

        case 'R':
        case 'r':
            if (strcEQ(var, "REQUEST_METHOD"))
                result = r->method;
            else if (strcEQ(var, "REQUEST_SCHEME"))
                result = ap_http_scheme(r);
            else if (strcEQ(var, "REQUEST_URI"))
                result = r->uri;
            else if (strcEQ(var, "REQUEST_FILENAME"))
                result = r->filename;
            else if (strcEQ(var, "REMOTE_ADDR"))
                result = r->useragent_ip;
            else if (strcEQ(var, "REMOTE_HOST"))
                result = ap_get_remote_host(r->connection, r->per_dir_config,
                                            REMOTE_NAME, NULL);
            else if (strcEQ(var, "REMOTE_IDENT"))
                result = ap_get_remote_logname(r);
            else if (strcEQ(var, "REMOTE_USER"))
                result = r->user;
            break;

        case 'S':
        case 's':
            if (strcEQn(var, "SSL", 3)) break; /* shortcut common case */

            if (strcEQ(var, "SERVER_ADMIN"))
                result = r->server->server_admin;
            else if (strcEQ(var, "SERVER_NAME"))
                result = ap_get_server_name_for_url(r);
            else if (strcEQ(var, "SERVER_PORT"))
                result = apr_psprintf(p, "%u", ap_get_server_port(r));
            else if (strcEQ(var, "SERVER_PROTOCOL"))
                result = r->protocol;
            else if (strcEQ(var, "SCRIPT_FILENAME"))
                result = r->filename;
            break;

        default:
            if (strcEQ(var, "PATH_INFO"))
                result = r->path_info;
            else if (strcEQ(var, "QUERY_STRING"))
                result = r->args;
            else if (strcEQ(var, "IS_SUBREQ"))
                result = (r->main != NULL ? "true" : "false");
            else if (strcEQ(var, "DOCUMENT_ROOT"))
                result = ap_document_root(r);
            else if (strcEQ(var, "AUTH_TYPE"))
                result = r->ap_auth_type;
            else if (strcEQ(var, "THE_REQUEST"))
                result = r->the_request;
            break;
        }
    }

    /*
     * Connection stuff
     */
    if (result == NULL && c != NULL) {
        /* XXX-Can't get specific SSL info from NetWare */
        /* SSLConnRec *sslconn = myConnConfig(c);
        if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
            && sslconn && sslconn->ssl)
            result = ssl_var_lookup_ssl(p, c, var+4);*/

        if (strlen(var) > 4 && strcEQn(var, "SSL_", 4))
            result = NULL;
    }

    /*
     * Totally independent stuff
     */
    if (result == NULL) {
        if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12))
            result = NULL;
            /* XXX-Can't get specific SSL info from NetWare */
            /*result = ssl_var_lookup_ssl_version(p, var+12);*/
        else if (strcEQ(var, "SERVER_SOFTWARE"))
            result = ap_get_server_banner();
        else if (strcEQ(var, "API_VERSION")) {
            result = apr_itoa(p, MODULE_MAGIC_NUMBER);
            resdup = FALSE;
        }
        else if (strcEQ(var, "TIME_YEAR")) {
            apr_time_exp_lt(&tm, apr_time_now());
            result = apr_psprintf(p, "%02d%02d",
                                 (tm.tm_year / 100) + 19, tm.tm_year % 100);
            resdup = FALSE;
        }
#define MKTIMESTR(format, tmfield) \
            apr_time_exp_lt(&tm, apr_time_now()); \
            result = apr_psprintf(p, format, tm.tmfield); \
            resdup = FALSE;
        else if (strcEQ(var, "TIME_MON")) {
            MKTIMESTR("%02d", tm_mon+1)
        }
        else if (strcEQ(var, "TIME_DAY")) {
            MKTIMESTR("%02d", tm_mday)
        }
        else if (strcEQ(var, "TIME_HOUR")) {
            MKTIMESTR("%02d", tm_hour)
        }
        else if (strcEQ(var, "TIME_MIN")) {
            MKTIMESTR("%02d", tm_min)
        }
        else if (strcEQ(var, "TIME_SEC")) {
            MKTIMESTR("%02d", tm_sec)
        }
        else if (strcEQ(var, "TIME_WDAY")) {
            MKTIMESTR("%d", tm_wday)
        }
        else if (strcEQ(var, "TIME")) {
            apr_time_exp_lt(&tm, apr_time_now());
            result = apr_psprintf(p,
                        "%02d%02d%02d%02d%02d%02d%02d", (tm.tm_year / 100) + 19,
                        (tm.tm_year % 100), tm.tm_mon+1, tm.tm_mday,
                        tm.tm_hour, tm.tm_min, tm.tm_sec);
            resdup = FALSE;
        }
        /* all other env-variables from the parent Apache process */
        else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) {
            result = apr_table_get(r->notes, var+4);
            if (result == NULL)
                result = apr_table_get(r->subprocess_env, var+4);
            if (result == NULL)
                result = getenv(var+4);
        }
    }

    if (result != NULL && resdup)
        result = apr_pstrdup(p, result);
    if (result == NULL)
        result = "";
    return (char *)result;
}

#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols"
#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
#define CONNECTION_HEADER "Connection: Upgrade"

static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f,
                                          apr_bucket_brigade *bb)

{
    const char *upgrade;
    apr_bucket_brigade *upgradebb;
    request_rec *r = f->r;
    apr_socket_t *csd = NULL;
    char *key;
    int ret;
    secsocket_data *csd_data;
    apr_bucket *b;
    apr_status_t rv;

    /* Just remove the filter, if it doesn't work the first time, it won't
     * work at all for this request.
     */
    ap_remove_output_filter(f);

    if (!r) {
        /*
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02131)
                     "Unable to get upgradeable socket handle");
        */
        return ap_pass_brigade(f->next, bb);
    }

    /* No need to ensure that this is a server with optional SSL, the filter
     * is only inserted if that is true.
     */

    upgrade = apr_table_get(r->headers_in, "Upgrade");
    if (upgrade == NULL
        || strcmp(ap_getword(r->pool, &upgrade, ','), "TLS/1.0")) {
            /* "Upgrade: TLS/1.0, ..." header not found, don't do Upgrade */
        return ap_pass_brigade(f->next, bb);
    }

    apr_table_unset(r->headers_out, "Upgrade");

    csd_data = (secsocket_data*)ap_get_module_config(r->connection->conn_config, &nwssl_module);
    csd = csd_data->csd;

    /* Send the interim 101 response. */
    upgradebb = apr_brigade_create(r->pool, f->c->bucket_alloc);

    ap_fputstrs(f->next, upgradebb, SWITCH_STATUS_LINE, CRLF,
                UPGRADE_HEADER, CRLF, CONNECTION_HEADER, CRLF, CRLF, NULL);

    b = apr_bucket_flush_create(f->c->bucket_alloc);
    APR_BRIGADE_INSERT_TAIL(upgradebb, b);

    rv = ap_pass_brigade(f->next, upgradebb);
    if (rv) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02132)
                      "could not send interim 101 Upgrade response");
        return AP_FILTER_ERROR;
    }

    key = get_port_key(r->connection);

    if (csd && key) {
        int sockdes;
        apr_os_sock_get(&sockdes, csd);

        ret = SSLize_Socket(sockdes, key, r);
        if (!ret) {
            csd_data->is_secure = 1;
        }
    }
    else {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02133)
                     "Upgradeable socket handle not found");
        return AP_FILTER_ERROR;
    }

    ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, APLOGNO(02134)
                 "Awaiting re-negotiation handshake");

    /* Now that we have initialized the ssl connection which added the ssl_io_filter,
       pass the brigade off to the connection based output filters so that the
       request can complete encrypted */
    return ap_pass_brigade(f->c->output_filters, bb);
}

static void ssl_hook_Insert_Filter(request_rec *r)
{
    NWSSLSrvConfigRec *sc = get_nwssl_cfg(r->server);

    if (isSecureUpgradeable (r)) {
        ap_add_output_filter("UPGRADE_FILTER", NULL, r, r->connection);
    }
}

static const command_rec nwssl_module_cmds[] =
{
    AP_INIT_TAKE23("SecureListen", set_secure_listener, NULL, RSRC_CONF,
      "specify an address and/or port with a key pair name.\n"
      "Optional third parameter of MUTUAL configures the port for mutual authentication."),
    AP_INIT_TAKE2("NWSSLUpgradeable", set_secure_upgradeable_listener, NULL, RSRC_CONF,
      "specify an address and/or port with a key pair name, that can be upgraded to an SSL connection.\n"
      "The address and/or port must have already be defined using a Listen directive."),
    AP_INIT_ITERATE("NWSSLTrustedCerts", set_trusted_certs, NULL, RSRC_CONF,
        "Adds trusted certificates that are used to create secure connections to proxied servers"),
    {NULL}
};

static void register_hooks(apr_pool_t *p)
{
    ap_register_output_filter ("UPGRADE_FILTER", ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);

    ap_hook_pre_config(nwssl_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_pre_connection(nwssl_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_post_config(nwssl_post_config, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_fixups(nwssl_hook_Fixup, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_http_scheme(nwssl_hook_http_scheme, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_default_port(nwssl_hook_default_port, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_insert_filter(ssl_hook_Insert_Filter, NULL, NULL, APR_HOOK_MIDDLE);

    APR_REGISTER_OPTIONAL_FN(ssl_is_https);
    APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);

    APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
    APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
}

AP_DECLARE_MODULE(nwssl) =
{
    STANDARD20_MODULE_STUFF,
    NULL,                       /* dir config creater */
    NULL,                       /* dir merger --- default is to override */
    nwssl_config_server_create, /* server config */
    nwssl_config_server_merge,  /* merge server config */
    nwssl_module_cmds,          /* command apr_table_t */
    register_hooks
};


text:
// Copyright 2021 The Bazel Authors. All rights reserved.
//
// 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.
package com.google.devtools.build.lib.skyframe;

import static com.google.devtools.build.lib.skyframe.BuildDriverKey.TestType.NOT_TEST;
import static com.google.devtools.build.lib.skyframe.BuildDriverKey.TestType.PARALLEL;

import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.actions.ActionLookupValue;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AspectValue;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.ExtraActionArtifactsProvider;
import com.google.devtools.build.lib.analysis.TopLevelArtifactContext;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.concurrent.Sharder;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.skyframe.ArtifactConflictFinder.ConflictException;
import com.google.devtools.build.lib.skyframe.AspectCompletionValue.AspectCompletionKey;
import com.google.devtools.build.lib.util.RegexFilter;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunction.Environment.SkyKeyComputeState;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Drives the analysis & execution of an ActionLookupKey, which is wrapped inside a BuildDriverKey.
 */
public class BuildDriverFunction implements SkyFunction {
  private final TransitiveActionLookupValuesCollector transitiveActionLookupValuesCollector;
  private final Supplier<IncrementalArtifactConflictFinder> incrementalArtifactConflictFinder;
  private final Supplier<EventBus> eventBus;

  BuildDriverFunction(
      TransitiveActionLookupValuesCollector transitiveActionLookupValuesCollector,
      Supplier<IncrementalArtifactConflictFinder> incrementalArtifactConflictFinder,
      Supplier<EventBus> eventBus) {
    this.transitiveActionLookupValuesCollector = transitiveActionLookupValuesCollector;
    this.incrementalArtifactConflictFinder = incrementalArtifactConflictFinder;
    this.eventBus = eventBus;
  }

  private static class State implements SkyKeyComputeState {
    private ImmutableMap<ActionAnalysisMetadata, ConflictException> actionConflicts;
    private boolean sentTestAnalysisCompleteEvent = false;
  }
  /**
   * From the ConfiguredTarget/Aspect keys, get the top-level artifacts. Then evaluate them together
   * with the appropriate CompletionFunctions. This is the bridge between the conceptual analysis &
   * execution phases.
   *
   * <p>TODO(b/199053098): implement build-info, build-changelist, coverage & exception handling.
   */
  @Nullable
  @Override
  public SkyValue compute(SkyKey skyKey, Environment env)
      throws SkyFunctionException, InterruptedException {
    BuildDriverKey buildDriverKey = (BuildDriverKey) skyKey;
    ActionLookupKey actionLookupKey = buildDriverKey.getActionLookupKey();
    TopLevelArtifactContext topLevelArtifactContext = buildDriverKey.getTopLevelArtifactContext();
    State state = env.getState(State::new);

    // Register a dependency on the BUILD_ID. We do this to make sure BuildDriverFunction is
    // reevaluated every build.
    PrecomputedValue.BUILD_ID.get(env);

    // Why SkyValue and not ActionLookupValue? The evaluation of some ActionLookupKey can result in
    // classes that don't implement ActionLookupValue
    // (e.g. ConfiguredTargetKey -> NonRuleConfiguredTargetValue).
    SkyValue topLevelSkyValue = env.getValue(actionLookupKey);

    if (env.valuesMissing()) {
      return null;
    }

    // Unconditionally check for action conflicts.
    // TODO(b/214371092): Only check when necessary.
    try (SilentCloseable c =
        Profiler.instance().profile("BuildDriverFunction.checkActionConflicts")) {
      if (state.actionConflicts == null) {
        state.actionConflicts =
            checkActionConflicts(actionLookupKey, buildDriverKey.strictActionConflictCheck());
      }
      if (!state.actionConflicts.isEmpty()) {
        throw new BuildDriverFunctionException(
            new TopLevelConflictException(
                "Action conflict(s) detected while analyzing top-level target "
                    + actionLookupKey.getLabel(),
                state.actionConflicts));
      }
    }

    Preconditions.checkState(
        topLevelSkyValue instanceof ConfiguredTargetValue
            || topLevelSkyValue instanceof TopLevelAspectsValue);
    if (topLevelSkyValue instanceof ConfiguredTargetValue) {
      requestConfiguredTargetExecution(
          ((ConfiguredTargetValue) topLevelSkyValue).getConfiguredTarget(),
          buildDriverKey,
          actionLookupKey,
          env,
          topLevelArtifactContext,
          state);
    } else {
      requestAspectExecution((TopLevelAspectsValue) topLevelSkyValue, env, topLevelArtifactContext);
    }

    return env.valuesMissing() ? null : new BuildDriverValue(topLevelSkyValue);
  }

  private void requestConfiguredTargetExecution(
      ConfiguredTarget configuredTarget,
      BuildDriverKey buildDriverKey,
      ActionLookupKey actionLookupKey,
      Environment env,
      TopLevelArtifactContext topLevelArtifactContext,
      State state)
      throws InterruptedException {
    ImmutableSet.Builder<Artifact> artifactsToBuild = ImmutableSet.builder();
    addExtraActionsIfRequested(
        configuredTarget.getProvider(ExtraActionArtifactsProvider.class), artifactsToBuild);
    if (buildDriverKey.getTestType() == NOT_TEST) {
      env.getValues(
          Iterables.concat(
              artifactsToBuild.build(),
              Collections.singletonList(
                  TargetCompletionValue.key(
                      (ConfiguredTargetKey) actionLookupKey, topLevelArtifactContext, false))));
      return;
    }

    if (!state.sentTestAnalysisCompleteEvent) {
      SkyValue buildConfigurationValue = env.getValue(configuredTarget.getConfigurationKey());
      if (env.valuesMissing()) {
        return;
      }
      eventBus
          .get()
          .post(
              new TestAnalysisCompleteEvent(
                  configuredTarget, (BuildConfigurationValue) buildConfigurationValue));
      state.sentTestAnalysisCompleteEvent = true;
    }

    Preconditions.checkState(
        PARALLEL.equals(buildDriverKey.getTestType()),
        "Invalid test type, expect only parallel tests: %s",
        buildDriverKey);
    // Only run non-exclusive tests here. Exclusive tests need to be run sequentially later.
    env.getValues(
        Iterables.concat(
            artifactsToBuild.build(),
            Collections.singletonList(
                TestCompletionValue.key(
                    (ConfiguredTargetKey) actionLookupKey,
                    topLevelArtifactContext,
                    /*exclusiveTesting=*/ false))));
  }

  private void requestAspectExecution(
      TopLevelAspectsValue topLevelAspectsValue,
      Environment env,
      TopLevelArtifactContext topLevelArtifactContext)
      throws InterruptedException {

    ImmutableSet.Builder<Artifact> artifactsToBuild = ImmutableSet.builder();
    List<SkyKey> aspectCompletionKeys = new ArrayList<>();
    for (SkyValue aspectValue : topLevelAspectsValue.getTopLevelAspectsValues()) {
      addExtraActionsIfRequested(
          ((AspectValue) aspectValue)
              .getConfiguredAspect()
              .getProvider(ExtraActionArtifactsProvider.class),
          artifactsToBuild);
      aspectCompletionKeys.add(
          AspectCompletionKey.create(
              ((AspectValue) aspectValue).getKey(), topLevelArtifactContext));
    }
    env.getValues(Iterables.concat(artifactsToBuild.build(), aspectCompletionKeys));
  }

  private ImmutableMap<ActionAnalysisMetadata, ConflictException> checkActionConflicts(
      ActionLookupKey actionLookupKey, boolean strictConflictCheck) throws InterruptedException {
    return incrementalArtifactConflictFinder
        .get()
        .findArtifactConflicts(
            transitiveActionLookupValuesCollector.collect(actionLookupKey), strictConflictCheck)
        .getConflicts();
  }

  private void addExtraActionsIfRequested(
      ExtraActionArtifactsProvider provider, ImmutableSet.Builder<Artifact> artifactsToBuild) {
    if (provider != null) {
      addArtifactsToBuilder(
          provider.getTransitiveExtraActionArtifacts().toList(), artifactsToBuild, null);
    }
  }

  private static void addArtifactsToBuilder(
      List<? extends Artifact> artifacts,
      ImmutableSet.Builder<Artifact> builder,
      RegexFilter filter) {
    for (Artifact artifact : artifacts) {
      if (filter.isIncluded(artifact.getOwnerLabel().toString())) {
        builder.add(artifact);
      }
    }
  }

  /** A SkyFunctionException wrapper for the actual TopLevelConflictException. */
  private static final class BuildDriverFunctionException extends SkyFunctionException {
    // The exception is transient here since it could be caused by external factors (conflict with
    // another target).
    BuildDriverFunctionException(TopLevelConflictException cause) {
      super(cause, Transience.TRANSIENT);
    }
  }

  interface TransitiveActionLookupValuesCollector {
    Sharder<ActionLookupValue> collect(ActionLookupKey key) throws InterruptedException;
  }
}

redpajama_set_name: RedPajamaGithub


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?attr/umeng_comm_album_text" >

    <android.support.v4.view.ViewPager
        android:id="@+id/umeng_comm_vp_base_app"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/layout_title_heigh_img"
        android:id="@+id/transhlate_layout"
        android:background="@android:color/transparent"
        android:layout_alignParentTop="true">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:id="@+id/translate_bg"
            android:layout_alignParentTop="true"
            android:background="?attr/umeng_comm_album_text"
            android:alpha="0.2"
            />
        <Button
            android:id="@+id/check_image"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:layout_marginTop="55dp"
            android:layout_marginRight="10dp"
            android:background="?attr/umeng_comm_album_choose_btn"
            />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/umeng_comm_layout_top_app"
        android:layout_width="match_parent"
        android:layout_height="@dimen/layout_title_heigh"
        android:layout_alignParentTop="true"
        android:background="?attr/default_background_color" >

        <ImageView
            android:id="@+id/umeng_comm_btn_back_app"
            android:layout_width="37dp"
            android:layout_height="37dp"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="5dp"
            android:src="?attr/umeng_comm_backbutton_src"
            android:scaleType="centerInside"/>
        <TextView
            android:id="@+id/umeng_comm_tv_percent_app"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_centerInParent="true"
            android:textSize="18dp"
            android:background="?attr/default_background_color"
            android:textColor="?attr/umeng_comm_active_user_name_textcolor" />
        <TextView
            android:id="@+id/umeng_comm_check_percent_app"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="20dp"
            android:gravity="center"
            android:textSize="13dp"
            android:background="?attr/umeng_comm_album_percent_btn"
            android:textColor="?attr/default_background_color" />

    </RelativeLayout>

</RelativeLayout>


text:
import image from '../graphics/gfx-image';
import renderImage from './render-image';

export default function renderText (canvas, text) {
    if (text.cached && (text.cached.x !== text.x || text.cached.y !== text.y)) {
        const { x, y, cached } = text;
        return renderImage(canvas, Object.assign(cached, { x, y }));
    }

    if (text.cached) {
        return renderImage(canvas, text.cached);
    }

    const cache = document.createElement('canvas');
    const cacheContext = cache.getContext('2d');
    const { content, x, y, style } = text;
    const { font, fill, stroke } = style;
    const fontString = `${ font.style } ${ font.weight } ${ font.size }px ${ font.family }`.trim();

    cacheContext.font = fontString;
    cache.width = Math.ceil(cacheContext.measureText(content).width + (stroke.width * 2)) || 1;
    cache.height = Math.ceil((font.size * 1.2) + (stroke.width * 2)) || 1;

    cacheContext.imageSmoothingEnabled = false;
    cacheContext.fillStyle = 'transparent';
    cacheContext.strokeStyle = 'transparent';

    cacheContext.font = fontString;
    cacheContext.textAlign = 'left';
    cacheContext.textBaseline = 'top';

    if (stroke.color) {
        cacheContext.strokeStyle = stroke.color;
        cacheContext.lineWidth = stroke.width * 2 || 2;
        cacheContext.strokeText(
            content,
            Math.round(stroke.width),
            Math.round(stroke.width)
        );
    }

    if (fill) {
        cacheContext.fillStyle = fill;
        cacheContext.fillText(
            content,
            Math.round(stroke.width),
            Math.round(stroke.width)
        );
    }

    text.cached = image({ data: cache, x, y });

    return renderImage(canvas, text.cached);
}


text:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;

namespace PTrampert.Webpack.CacheBuster
{
    public class CacheBuster : ICacheBuster
    {
        private readonly IDictionary<string, CacheBustedFile> cache = new ConcurrentDictionary<string, CacheBustedFile>();

        private readonly IWebHostEnvironment env;
        private readonly IUrlHelperFactory urlHelperFactory;
        private readonly IActionContextAccessor actionContextAccessor;

        public CacheBuster(IWebHostEnvironment env, IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionContextAccessor)
        {
            this.env = env;
            this.urlHelperFactory = urlHelperFactory;
            this.actionContextAccessor = actionContextAccessor;
        }

        public string BustCache(string url)
        {
            var webroot = env.WebRootFileProvider;
            var urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext);
            var absoluteUrl = urlHelper.Content(url);
            if (!cache.ContainsKey(absoluteUrl))
            {
                cache.Add(absoluteUrl, new CacheBustedFile(absoluteUrl));
            }

            var cachedFile = cache[absoluteUrl];

            if (!cachedFile.Exists(webroot))
            {
                return absoluteUrl;
            }

            cachedFile.LastChecked = DateTimeOffset.Now;

            return $"{cachedFile.WebPath}?v={cachedFile.GetHash(webroot)}";
        }
    }
}


text:
<?php

namespace Glr\StorebackBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * SocioArticulo
 *
 * @ORM\Table(name="Socio_Articulo", indexes={@ORM\Index(name="fk_Socio-Articulo_1_idx", columns={"idSocio"})})
 * @ORM\Entity
 */
class SocioArticulo
{
    /**
     * @var string
     *
     * @ORM\Column(name="pedido_socio", type="string", length=15, nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $pedidoSocio;

    /**
     * @var integer
     *
     * @ORM\Column(name="id_art", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $idArt;

    /**
     * @var integer
     *
     * @ORM\Column(name="idSocio", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $idsocio;

    /**
     * @var string
     *
     * @ORM\Column(name="idsocio_art", type="string", length=15, nullable=false)
     */
    private $idsocioArt;

    /**
     * @var string
     *
     * @ORM\Column(name="cantidad", type="decimal", precision=6, scale=0, nullable=true)
     */
    private $cantidad = '0';

    /**
     * @var string
     *
     * @ORM\Column(name="precio", type="decimal", precision=11, scale=2, nullable=true)
     */
    private $precio = '0.00';

}


text:
Jsonnet to Java
---------------

This little code example shows how a Jsonnet config using object-oriented features can be
transliterated (in a structure-preserving manner) to use the object-oriented features of Java.  Not
all Jsonnet programs can be converted to Java because Jsonnet has mixins and virtual inner classes.
Execution order is also different, as Jsonnet is lazy and Java is eager.  Likewise, Java programs
cannot all be converted to Jsonnet because they have mutable state and I/O.

However said all this, there is a significant overlap between the two languages.  This example fits
within that overlap.

Execute Jsonnet code
--------------------

```
jsonnet sub-template.jsonnet
```

Execute Java code
-----------------

We pipe into jsonnet - to pretty-print the output JSON.

```
javac *.java && java Test | jsonnet -
```

Structure of Java code
----------------------

The translation is as as follows:

* Everything is typed as Object, as Jsonnet is dynamically typed.  Everything is public, as is implicit in Jsonnet.
* Jsonnet arrays are Object[], and primitives are Boolean / Double / String.
* Jsonnet objects are singleton instances of named Java classes that extend JsonnetObject.
* Jsonnet fields become Java methods with no parameters (fields are virtual in Jsonnet).
* Jsonnet hidden field status is represented with a method nonHiddenFields which returns a set of
  field names.  Other fields are considered hidden.
* There are 2 liberties taken -- output strings are not escaped properly, and the JSON is printed on
  a single line instead of pretty-printed with indenting.

The Java code has a number of auxiliary framework functions to provide Jsonnet functionality that is
implicit in the Jsonnet language.

* The Test class chooses an object and manifests it to stdout.
* The JsonnetValue class implements manifestation, as a visitor over possible JSON values that
  builds JSON strings.  For objects, it iterates over the non-hidden fields and manifests each value
  by reflectively calling that function.

Reference JSON
--------------

For reference, the JSON that should be output is given in sub-template.json


text:
package play.api.test

import play.api._
import play.api.inject.guice.GuiceApplicationBuilder
import play.core.server._
import scala.util.control.NonFatal

/**
 * A test web server.
 *
 * @param config The server configuration.
 * @param application The Application to load in this server.
 * @param serverProvider The type of server to use. If not provided, uses Play's default provider.
 */
case class TestServer(
    config: ServerConfig,
    application: Application,
    serverProvider: Option[ServerProvider]) {

  private var testServerProcess: TestServerProcess = _

  /**
   * Starts this server.
   */
  def start() {
    if (testServerProcess != null) {
      sys.error("Server already started!")
    }

    try {
      testServerProcess = TestServer.start(serverProvider, config, application)
    } catch {
      case NonFatal(t) =>
        t.printStackTrace
        throw new RuntimeException(t)
    }
  }

  /**
   * Stops this server.
   */
  def stop() {
    if (testServerProcess != null) {
      val shuttingDownProcess = testServerProcess
      testServerProcess = null
      shuttingDownProcess.shutdown()
    }
  }

  /**
   * The port that the server is running on.
   */
  def port: Int = config.port.getOrElse(throw new IllegalStateException("No HTTP port defined"))
}

object TestServer {

  /**
   * A test web server.
   *
   * @param port HTTP port to bind on.
   * @param application The Application to load in this server.
   * @param sslPort HTTPS port to bind on.
   * @param serverProvider The type of server to use. If not provided, uses Play's default provider.
   */
  def apply(
    port: Int,
    application: Application = GuiceApplicationBuilder().build(),
    sslPort: Option[Int] = None,
    serverProvider: Option[ServerProvider] = None) = new TestServer(
    ServerConfig(port = Some(port), sslPort = sslPort, mode = Mode.Test,
      rootDir = application.path), application, serverProvider
  )

  /**
   * Start a TestServer with the given config and application. To stop it,
   * call `shutdown` on the returned TestServerProcess.
   */
  private[play] def start(
    testServerProvider: Option[ServerProvider],
    config: ServerConfig,
    application: Application): TestServerProcess = {
    val process = new TestServerProcess
    val serverProvider: ServerProvider = {
      testServerProvider
    } getOrElse {
      ServerProvider.fromConfiguration(process.classLoader, config.configuration)
    }
    Play.start(application)
    val server = serverProvider.createServer(config, application)
    process.addShutdownHook { server.stop() }
    process
  }

}

/**
 * A mock system process for a TestServer to run within. A ServerProcess
 * can mock command line arguments, System properties, a ClassLoader,
 * System.exit calls and shutdown hooks.
 *
 * When the process is finished, call `shutdown()` to run all registered
 * shutdown hooks.
 */
private[play] class TestServerProcess extends ServerProcess {

  private var hooks = Seq.empty[() => Unit]
  override def addShutdownHook(hook: => Unit) = {
    hooks = hooks :+ (() => hook)
  }
  def shutdown(): Unit = {
    for (h <- hooks) h.apply()
  }

  override def classLoader = getClass.getClassLoader
  override def args = Seq()
  override def properties = System.getProperties
  override def pid = None

  override def exit(message: String, cause: Option[Throwable] = None, returnCode: Int = -1): Nothing = {
    throw new TestServerExitException(message, cause, returnCode)
  }

}

private[play] case class TestServerExitException(
  message: String,
  cause: Option[Throwable] = None,
  returnCode: Int = -1) extends Exception(s"Exit with $message, $cause, $returnCode", cause.orNull)


text:
package org.apache.solr.analytics.function.mapping;

import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.analytics.value.AnalyticsValue;
import org.apache.solr.analytics.value.AnalyticsValueStream;
import org.apache.solr.analytics.value.BooleanValue;
import org.apache.solr.analytics.value.BooleanValueStream;
import org.apache.solr.analytics.value.DateValue;
import org.apache.solr.analytics.value.DateValueStream;
import org.apache.solr.analytics.value.DoubleValue;
import org.apache.solr.analytics.value.DoubleValueStream;
import org.apache.solr.analytics.value.FillableTestValue.TestAnalyticsValue;
import org.apache.solr.analytics.value.FillableTestValue.TestAnalyticsValueStream;
import org.apache.solr.analytics.value.FillableTestValue.TestBooleanValue;
import org.apache.solr.analytics.value.FillableTestValue.TestBooleanValueStream;
import org.apache.solr.analytics.value.FillableTestValue.TestDateValue;
import org.apache.solr.analytics.value.FillableTestValue.TestDateValueStream;
import org.apache.solr.analytics.value.FillableTestValue.TestDoubleValue;
import org.apache.solr.analytics.value.FillableTestValue.TestDoubleValueStream;
import org.apache.solr.analytics.value.FillableTestValue.TestFloatValue;
import org.apache.solr.analytics.value.FillableTestValue.TestFloatValueStream;
import org.apache.solr.analytics.value.FillableTestValue.TestIntValue;
import org.apache.solr.analytics.value.FillableTestValue.TestIntValueStream;
import org.apache.solr.analytics.value.FillableTestValue.TestLongValue;
import org.apache.solr.analytics.value.FillableTestValue.TestLongValueStream;
import org.apache.solr.analytics.value.FillableTestValue.TestStringValue;
import org.apache.solr.analytics.value.FillableTestValue.TestStringValueStream;
import org.apache.solr.analytics.value.FloatValue;
import org.apache.solr.analytics.value.FloatValueStream;
import org.apache.solr.analytics.value.IntValue;
import org.apache.solr.analytics.value.IntValueStream;
import org.apache.solr.analytics.value.LongValue;
import org.apache.solr.analytics.value.LongValueStream;
import org.apache.solr.analytics.value.StringValue;
import org.apache.solr.analytics.value.StringValueStream;
import org.junit.Test;

public class FilterFunctionTest extends SolrTestCaseJ4 {

  @Test
  public void singleValueBooleanTest() {
    TestBooleanValue val = new TestBooleanValue();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof BooleanValue);
    BooleanValue func = (BooleanValue) uncasted;

    // Value doesn't exist
    val.setExists(false);
    filter.setExists(false);
    func.getBoolean();
    assertFalse(func.exists());

    val.setValue(true).setExists(true);
    filter.setExists(false);
    func.getBoolean();
    assertFalse(func.exists());

    val.setExists(false);
    filter.setValue(true).setExists(true);
    func.getBoolean();
    assertFalse(func.exists());

    // Value exists
    val.setValue(true).setExists(true);
    filter.setValue(true).setExists(true);
    assertTrue(func.getBoolean());
    assertTrue(func.exists());

    val.setValue(true).setExists(true);
    filter.setValue(false).setExists(true);
    func.getBoolean();
    assertFalse(func.exists());

    val.setValue(false).setExists(true);
    filter.setValue(true).setExists(true);
    assertFalse(func.getBoolean());
    assertTrue(func.exists());

    val.setValue(false).setExists(true);
    filter.setValue(false).setExists(true);
    func.getBoolean();
    assertFalse(func.exists());
  }

  @Test
  public void singleValueIntTest() {
    TestIntValue val = new TestIntValue();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof IntValue);
    IntValue func = (IntValue) uncasted;

    // Value doesn't exist
    val.setExists(false);
    filter.setExists(false);
    func.getInt();
    assertFalse(func.exists());

    val.setValue(32).setExists(true);
    filter.setExists(false);
    func.getInt();
    assertFalse(func.exists());

    val.setExists(false);
    filter.setValue(true).setExists(true);
    func.getInt();
    assertFalse(func.exists());

    // Value exists
    val.setValue(21).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(21, func.getInt());
    assertTrue(func.exists());

    val.setValue(-100).setExists(true);
    filter.setValue(false).setExists(true);
    func.getInt();
    assertFalse(func.exists());

    val.setValue(50).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(50, func.getInt());
    assertTrue(func.exists());

    val.setValue(5432).setExists(true);
    filter.setValue(false).setExists(true);
    func.getInt();
    assertFalse(func.exists());
  }

  @Test
  public void singleValueLongTest() {
    TestLongValue val = new TestLongValue();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof LongValue);
    LongValue func = (LongValue) uncasted;

    // Value doesn't exist
    val.setExists(false);
    filter.setExists(false);
    func.getLong();
    assertFalse(func.exists());

    val.setValue(32L).setExists(true);
    filter.setExists(false);
    func.getLong();
    assertFalse(func.exists());

    val.setExists(false);
    filter.setValue(true).setExists(true);
    func.getLong();
    assertFalse(func.exists());

    // Value exists
    val.setValue(21L).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(21L, func.getLong());
    assertTrue(func.exists());

    val.setValue(-100L).setExists(true);
    filter.setValue(false).setExists(true);
    func.getLong();
    assertFalse(func.exists());

    val.setValue(50L).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(50L, func.getLong());
    assertTrue(func.exists());

    val.setValue(3245L).setExists(true);
    filter.setValue(false).setExists(true);
    func.getLong();
    assertFalse(func.exists());
  }

  @Test
  public void singleValueFloatTest() {
    TestFloatValue val = new TestFloatValue();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof FloatValue);
    FloatValue func = (FloatValue) uncasted;

    // Value doesn't exist
    val.setExists(false);
    filter.setExists(false);
    func.getFloat();
    assertFalse(func.exists());

    val.setValue(32.123F).setExists(true);
    filter.setExists(false);
    func.getFloat();
    assertFalse(func.exists());

    val.setExists(false);
    filter.setValue(true).setExists(true);
    func.getFloat();
    assertFalse(func.exists());

    // Value exists
    val.setValue(21.453F).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(21.453F, func.getFloat(), .000001);
    assertTrue(func.exists());

    val.setValue(-100.123F).setExists(true);
    filter.setValue(false).setExists(true);
    func.getFloat();
    assertFalse(func.exists());

    val.setValue(50.5F).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(50.5F, func.getFloat(), .000001);
    assertTrue(func.exists());

    val.setValue(25643.23F).setExists(true);
    filter.setValue(false).setExists(true);
    func.getFloat();
    assertFalse(func.exists());
  }

  @Test
  public void singleValueDoubleTest() {
    TestDoubleValue val = new TestDoubleValue();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof DoubleValue);
    DoubleValue func = (DoubleValue) uncasted;

    // Value doesn't exist
    val.setExists(false);
    filter.setExists(false);
    func.getDouble();
    assertFalse(func.exists());

    val.setValue(32.123).setExists(true);
    filter.setExists(false);
    func.getDouble();
    assertFalse(func.exists());

    val.setExists(false);
    filter.setValue(true).setExists(true);
    func.getDouble();
    assertFalse(func.exists());

    // Value exists
    val.setValue(21.453).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(21.453, func.getDouble(), .000001);
    assertTrue(func.exists());

    val.setValue(-100.123).setExists(true);
    filter.setValue(false).setExists(true);
    func.getDouble();
    assertFalse(func.exists());

    val.setValue(50.5).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(50.5, func.getDouble(), .000001);
    assertTrue(func.exists());

    val.setValue(25643.23).setExists(true);
    filter.setValue(false).setExists(true);
    func.getDouble();
    assertFalse(func.exists());
  }

  @Test
  public void singleValueDateTest() throws DateTimeParseException {
    Date date1 = Date.from(Instant.parse("1810-12-02T10:30:15Z"));
    Date date3 = Date.from(Instant.parse("2023-11-01T20:30:15Z"));

    TestDateValue val = new TestDateValue();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof DateValue);
    DateValue func = (DateValue) uncasted;

    // Value doesn't exist
    val.setExists(false);
    filter.setExists(false);
    func.getLong();
    assertFalse(func.exists());

    val.setValue("1810-12-02T10:30:15Z").setExists(true);
    filter.setExists(false);
    func.getLong();
    assertFalse(func.exists());

    val.setExists(false);
    filter.setValue(true).setExists(true);
    func.getLong();
    assertFalse(func.exists());

    // Value exists
    val.setValue("1810-12-02T10:30:15Z").setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(date1.getTime(), func.getLong());
    assertTrue(func.exists());

    val.setValue("1931-03-16T18:15:45Z").setExists(true);
    filter.setValue(false).setExists(true);
    func.getLong();
    assertFalse(func.exists());

    val.setValue("2023-11-01T20:30:15Z").setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(date3.getTime(), func.getLong());
    assertTrue(func.exists());

    val.setValue("1810-12-02T10:30:15Z").setExists(true);
    filter.setValue(false).setExists(true);
    func.getLong();
    assertFalse(func.exists());
  }

  @Test
  public void singleValueStringTest() {
    TestStringValue val = new TestStringValue();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof StringValue);
    StringValue func = (StringValue) uncasted;

    // Value doesn't exist
    val.setExists(false);
    filter.setExists(false);
    func.getString();
    assertFalse(func.exists());

    val.setValue("abc123").setExists(true);
    filter.setExists(false);
    func.getString();
    assertFalse(func.exists());

    val.setExists(false);
    filter.setValue(true).setExists(true);
    func.getString();
    assertFalse(func.exists());

    // Value exists
    val.setValue("abc").setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals("abc", func.getString());
    assertTrue(func.exists());

    val.setValue("def").setExists(true);
    filter.setValue(false).setExists(true);
    func.getString();
    assertFalse(func.exists());

    val.setValue("123").setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals("123", func.getString());
    assertTrue(func.exists());

    val.setValue("456").setExists(true);
    filter.setValue(false).setExists(true);
    func.getString();
    assertFalse(func.exists());
  }

  @Test
  public void singleValueObjectTest() {
    TestAnalyticsValue val = new TestAnalyticsValue();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof AnalyticsValue);
    AnalyticsValue func = (AnalyticsValue) uncasted;

    // Value doesn't exist
    val.setExists(false);
    filter.setExists(false);
    func.getObject();
    assertFalse(func.exists());

    val.setValue("1810-12-02T10:30:15Z").setExists(true);
    filter.setExists(false);
    func.getObject();
    assertFalse(func.exists());

    val.setExists(false);
    filter.setValue(true).setExists(true);
    func.getObject();
    assertFalse(func.exists());

    // Value exists
    val.setValue(3L).setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals(3L, func.getObject());
    assertTrue(func.exists());

    val.setValue(new Date(2)).setExists(true);
    filter.setValue(false).setExists(true);
    func.getObject();
    assertFalse(func.exists());

    val.setValue("3").setExists(true);
    filter.setValue(true).setExists(true);
    assertEquals("3", func.getObject());
    assertTrue(func.exists());

    val.setValue(new TestAnalyticsValue()).setExists(true);
    filter.setValue(false).setExists(true);
    func.getObject();
    assertFalse(func.exists());
  }

  @Test
  public void multiValueBooleanTest() {
    TestBooleanValueStream val = new TestBooleanValueStream();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof BooleanValueStream);
    BooleanValueStream func = (BooleanValueStream) uncasted;

    // No values
    val.setValues();
    filter.setExists(false);
    func.streamBooleans(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues(false, true, false);
    filter.setExists(false);
    func.streamBooleans(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues();
    filter.setValue(true).setExists(true);
    func.streamBooleans(
        value -> {
          fail("There should be no values to stream");
        });

    // One value
    val.setValues(true);

    filter.setValue(true).setExists(true);
    Iterator<Boolean> values1 = Arrays.asList(true).iterator();
    func.streamBooleans(
        value -> {
          assertTrue(values1.hasNext());
          assertEquals(values1.next(), value);
        });
    assertFalse(values1.hasNext());

    filter.setValue(false).setExists(true);
    func.streamBooleans(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Boolean> values2 = Arrays.asList(true).iterator();
    func.streamBooleans(
        value -> {
          assertTrue(values2.hasNext());
          assertEquals(values2.next(), value);
        });
    assertFalse(values2.hasNext());

    // Multiple values
    val.setValues(false, false, true, true);

    filter.setValue(false).setExists(true);
    func.streamBooleans(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Boolean> values3 = Arrays.asList(false, false, true, true).iterator();
    func.streamBooleans(
        value -> {
          assertTrue(values3.hasNext());
          assertEquals(values3.next(), value);
        });
    assertFalse(values3.hasNext());

    filter.setValue(false).setExists(true);
    func.streamBooleans(
        value -> {
          fail("There should be no values to stream");
        });
  }

  @Test
  public void multiValueIntTest() {
    TestIntValueStream val = new TestIntValueStream();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof IntValueStream);
    IntValueStream func = (IntValueStream) uncasted;

    // No values
    val.setValues();
    filter.setExists(false);
    func.streamInts(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues(1, 3, 5);
    filter.setExists(false);
    func.streamInts(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues();
    filter.setValue(true).setExists(true);
    func.streamInts(
        value -> {
          fail("There should be no values to stream");
        });

    // One value
    val.setValues(-4);

    filter.setValue(true).setExists(true);
    Iterator<Integer> values1 = Arrays.asList(-4).iterator();
    func.streamInts(
        value -> {
          assertTrue(values1.hasNext());
          assertEquals(values1.next().intValue(), value);
        });
    assertFalse(values1.hasNext());

    filter.setValue(false).setExists(true);
    func.streamInts(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Integer> values2 = Arrays.asList(-4).iterator();
    func.streamInts(
        value -> {
          assertTrue(values2.hasNext());
          assertEquals(values2.next().intValue(), value);
        });
    assertFalse(values2.hasNext());

    // Multiple values
    val.setValues(4, -10, 50, -74);

    filter.setValue(false).setExists(true);
    func.streamInts(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Integer> values3 = Arrays.asList(4, -10, 50, -74).iterator();
    func.streamInts(
        value -> {
          assertTrue(values3.hasNext());
          assertEquals(values3.next().intValue(), value);
        });
    assertFalse(values3.hasNext());

    filter.setValue(false).setExists(true);
    func.streamInts(
        value -> {
          fail("There should be no values to stream");
        });
  }

  @Test
  public void multiValueLongTest() {
    TestLongValueStream val = new TestLongValueStream();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof LongValueStream);
    LongValueStream func = (LongValueStream) uncasted;

    // No values
    val.setValues();
    filter.setExists(false);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues(1L, 3L, 5L);
    filter.setExists(false);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues();
    filter.setValue(true).setExists(true);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    // One value
    val.setValues(-4L);

    filter.setValue(true).setExists(true);
    Iterator<Long> values1 = Arrays.asList(-4L).iterator();
    func.streamLongs(
        value -> {
          assertTrue(values1.hasNext());
          assertEquals(values1.next().longValue(), value);
        });
    assertFalse(values1.hasNext());

    filter.setValue(false).setExists(true);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Long> values2 = Arrays.asList(-4L).iterator();
    func.streamLongs(
        value -> {
          assertTrue(values2.hasNext());
          assertEquals(values2.next().longValue(), value);
        });
    assertFalse(values2.hasNext());

    // Multiple values
    val.setValues(4L, -10L, 50L, -74L);

    filter.setValue(false).setExists(true);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Long> values3 = Arrays.asList(4L, -10L, 50L, -74L).iterator();
    func.streamLongs(
        value -> {
          assertTrue(values3.hasNext());
          assertEquals(values3.next().longValue(), value);
        });
    assertFalse(values3.hasNext());

    filter.setValue(false).setExists(true);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });
  }

  @Test
  public void multiValueFloatTest() {
    TestFloatValueStream val = new TestFloatValueStream();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof FloatValueStream);
    FloatValueStream func = (FloatValueStream) uncasted;

    // No values
    val.setValues();
    filter.setExists(false);
    func.streamFloats(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues(50.343F, -74.9874F, 2.34233242E+9F);
    filter.setExists(false);
    func.streamFloats(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues();
    filter.setValue(true).setExists(true);
    func.streamFloats(
        value -> {
          fail("There should be no values to stream");
        });

    // One value
    val.setValues(-4.23423F);

    filter.setValue(true).setExists(true);
    Iterator<Float> values1 = Arrays.asList(-4.23423F).iterator();
    func.streamFloats(
        value -> {
          assertTrue(values1.hasNext());
          assertEquals(values1.next(), value, .0000001);
        });
    assertFalse(values1.hasNext());

    filter.setValue(false).setExists(true);
    func.streamFloats(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Float> values2 = Arrays.asList(-4.23423F).iterator();
    func.streamFloats(
        value -> {
          assertTrue(values2.hasNext());
          assertEquals(values2.next(), value, .0000001);
        });
    assertFalse(values2.hasNext());

    // Multiple values
    val.setValues(4.3F, -10.134F, 50.343F, -74.9874F);

    filter.setValue(false).setExists(true);
    func.streamFloats(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Float> values3 = Arrays.asList(4.3F, -10.134F, 50.343F, -74.9874F).iterator();
    func.streamFloats(
        value -> {
          assertTrue(values3.hasNext());
          assertEquals(values3.next(), value, .0000001);
        });
    assertFalse(values3.hasNext());

    filter.setValue(false).setExists(true);
    func.streamFloats(
        value -> {
          fail("There should be no values to stream");
        });
  }

  @Test
  public void multiValueDoubleTest() {
    TestDoubleValueStream val = new TestDoubleValueStream();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof DoubleValueStream);
    DoubleValueStream func = (DoubleValueStream) uncasted;

    // No values
    val.setValues();
    filter.setExists(false);
    func.streamDoubles(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues(50.343, -74.9874, 2342332342.32);
    filter.setExists(false);
    func.streamDoubles(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues();
    filter.setValue(true).setExists(true);
    func.streamDoubles(
        value -> {
          fail("There should be no values to stream");
        });

    // One value
    val.setValues(-4.23423);

    filter.setValue(true).setExists(true);
    Iterator<Double> values1 = Arrays.asList(-4.23423).iterator();
    func.streamDoubles(
        value -> {
          assertTrue(values1.hasNext());
          assertEquals(values1.next(), value, .0000001);
        });
    assertFalse(values1.hasNext());

    filter.setValue(false).setExists(true);
    func.streamDoubles(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Double> values2 = Arrays.asList(-4.23423).iterator();
    func.streamDoubles(
        value -> {
          assertTrue(values2.hasNext());
          assertEquals(values2.next(), value, .0000001);
        });
    assertFalse(values2.hasNext());

    // Multiple values
    val.setValues(4.3, -10.134, 50.343, -74.9874);

    filter.setValue(false).setExists(true);
    func.streamDoubles(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Double> values3 = Arrays.asList(4.3, -10.134, 50.343, -74.9874).iterator();
    func.streamDoubles(
        value -> {
          assertTrue(values3.hasNext());
          assertEquals(values3.next(), value, .0000001);
        });
    assertFalse(values3.hasNext());

    filter.setValue(false).setExists(true);
    func.streamDoubles(
        value -> {
          fail("There should be no values to stream");
        });
  }

  @Test
  public void multiValueDateTest() throws DateTimeParseException {
    Date date1 = Date.from(Instant.parse("1810-12-02T10:30:15Z"));
    Date date2 = Date.from(Instant.parse("1931-03-16T18:15:45Z"));
    Date date3 = Date.from(Instant.parse("2023-11-01T20:30:15Z"));

    TestDateValueStream val = new TestDateValueStream();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof DateValueStream);
    DateValueStream func = (DateValueStream) uncasted;

    // No values
    val.setValues();
    filter.setExists(false);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues("1810-12-02T10:30:15Z", "1850-12-02T20:30:15Z");
    filter.setExists(false);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues();
    filter.setValue(true).setExists(true);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    // One value
    val.setValues("1810-12-02T10:30:15Z");

    filter.setValue(true).setExists(true);
    Iterator<Long> values1 = Arrays.asList(date1.getTime()).iterator();
    func.streamLongs(
        value -> {
          assertTrue(values1.hasNext());
          assertEquals(values1.next().longValue(), value);
        });
    assertFalse(values1.hasNext());

    filter.setValue(false).setExists(true);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Long> values2 = Arrays.asList(date1.getTime()).iterator();
    func.streamLongs(
        value -> {
          assertTrue(values2.hasNext());
          assertEquals(values2.next().longValue(), value);
        });
    assertFalse(values2.hasNext());

    // Multiple values
    val.setValues("1810-12-02T10:30:15Z", "1931-03-16T18:15:45Z", "2023-11-01T20:30:15Z");

    filter.setValue(false).setExists(true);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Long> values3 =
        Arrays.asList(date1.getTime(), date2.getTime(), date3.getTime()).iterator();
    func.streamLongs(
        value -> {
          assertTrue(values3.hasNext());
          assertEquals(values3.next().longValue(), value);
        });
    assertFalse(values3.hasNext());

    filter.setValue(false).setExists(true);
    func.streamLongs(
        value -> {
          fail("There should be no values to stream");
        });
  }

  @Test
  public void multiValueStringTest() {
    TestStringValueStream val = new TestStringValueStream();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream uncasted =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});
    assertTrue(uncasted instanceof StringValueStream);
    StringValueStream func = (StringValueStream) uncasted;

    // No values
    val.setValues();
    filter.setExists(false);
    func.streamStrings(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues("abc", "123", "def", "456");
    filter.setExists(false);
    func.streamStrings(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues();
    filter.setValue(true).setExists(true);
    func.streamStrings(
        value -> {
          fail("There should be no values to stream");
        });

    // One value
    val.setValues("abcdef");

    filter.setValue(true).setExists(true);
    Iterator<String> values1 = Arrays.asList("abcdef").iterator();
    func.streamStrings(
        value -> {
          assertTrue(values1.hasNext());
          assertEquals(values1.next(), value);
        });
    assertFalse(values1.hasNext());

    filter.setValue(false).setExists(true);
    func.streamStrings(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<String> values2 = Arrays.asList("abcdef").iterator();
    func.streamStrings(
        value -> {
          assertTrue(values2.hasNext());
          assertEquals(values2.next(), value);
        });
    assertFalse(values2.hasNext());

    // Multiple values
    val.setValues("abc", "123", "def", "456");

    filter.setValue(false).setExists(true);
    func.streamStrings(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<String> values3 = Arrays.asList("abc", "123", "def", "456").iterator();
    func.streamStrings(
        value -> {
          assertTrue(values3.hasNext());
          assertEquals(values3.next(), value);
        });
    assertFalse(values3.hasNext());

    filter.setValue(false).setExists(true);
    func.streamStrings(
        value -> {
          fail("There should be no values to stream");
        });
  }

  @Test
  public void multiValueObjectTest() {
    TestAnalyticsValueStream val = new TestAnalyticsValueStream();
    TestBooleanValue filter = new TestBooleanValue();

    AnalyticsValueStream func =
        FilterFunction.creatorFunction.apply(new AnalyticsValueStream[] {val, filter});

    // No values
    val.setValues();
    filter.setExists(false);
    func.streamObjects(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues(3, "3", new Date(3));
    filter.setExists(false);
    func.streamObjects(
        value -> {
          fail("There should be no values to stream");
        });

    val.setValues();
    filter.setValue(true).setExists(true);
    func.streamObjects(
        value -> {
          fail("There should be no values to stream");
        });

    // One value
    Object obj = new TestAnalyticsValueStream();
    val.setValues(obj);

    filter.setValue(true).setExists(true);
    Iterator<Object> values1 = Arrays.<Object>asList(obj).iterator();
    func.streamObjects(
        value -> {
          assertTrue(values1.hasNext());
          assertEquals(values1.next(), value);
        });
    assertFalse(values1.hasNext());

    filter.setValue(false).setExists(true);
    func.streamObjects(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Object> values2 = Arrays.<Object>asList(obj).iterator();
    func.streamObjects(
        value -> {
          assertTrue(values2.hasNext());
          assertEquals(values2.next(), value);
        });
    assertFalse(values2.hasNext());

    // Multiple values
    val.setValues(3, "3", new Date(3));

    filter.setValue(false).setExists(true);
    func.streamObjects(
        value -> {
          fail("There should be no values to stream");
        });

    filter.setValue(true).setExists(true);
    Iterator<Object> values3 = Arrays.<Object>asList(3, "3", new Date(3)).iterator();
    func.streamObjects(
        value -> {
          assertTrue(values3.hasNext());
          assertEquals(values3.next(), value);
        });
    assertFalse(values3.hasNext());

    filter.setValue(false).setExists(true);
    func.streamObjects(
        value -> {
          fail("There should be no values to stream");
        });
  }
}


text:
from channels.staticfiles import StaticFilesConsumer
from . import consumers

channel_routing = {
    'http.request': StaticFilesConsumer(),
    'websocket.connect': consumers.ws_connect,
    'websocket.receive': consumers.ws_receive,
    'websocket.disconnect': consumers.ws_disconnect,
}


text:
/**
 * Please, insert description here.
 *
 * @author Riccardo Cardin
 * @version 1.0
 * @since 1.0
 */
package it.unipd.math.pcd.actors.utils.actors.counter;

import it.unipd.math.pcd.actors.AbsActor;
import it.unipd.math.pcd.actors.utils.messages.counter.*;

/**
 * Please, insert description here.
 *
 * @author Riccardo Cardin
 * @version 1.0
 * @since 1.0
 */
public class CounterActor extends AbsActor<CounterMessage> {

    private int counter = 0;

    @Override
    public void receive(CounterMessage message) {
        if (message instanceof Increment) {
            counter++;
        } else if (message instanceof Decrement) {
            counter--;
        } else if (message instanceof Get) {
            self.send(new Result(counter), sender);
        }
    }

    public int getCounter() {
        return counter;
    }
}