All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kaazing.gateway.service.http.balancer.WsebBalancerServiceHandler Maven / Gradle / Ivy

/**
 * Copyright (c) 2007-2014 Kaazing Corporation. All rights reserved.
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.kaazing.gateway.service.http.balancer;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;

import org.kaazing.gateway.resource.address.Protocol;
import org.kaazing.gateway.service.cluster.ClusterContext;
import org.kaazing.gateway.service.messaging.collections.CollectionsFactory;
import org.kaazing.gateway.transport.IoHandlerAdapter;
import org.kaazing.gateway.transport.TransportFactory;
import org.kaazing.gateway.transport.http.HttpAcceptSession;
import org.kaazing.gateway.transport.http.HttpStatus;
import org.kaazing.gateway.transport.wseb.WsebAcceptor;
import org.kaazing.gateway.util.GL;

class WsebBalancerServiceHandler extends IoHandlerAdapter {
    private Collection accepts;
    private ClusterContext clusterContext;
    private TransportFactory transportFactory;

    WsebBalancerServiceHandler() {
    }

    Collection getAccepts() {
        return accepts;
    }

    void setAccepts(Collection accepts) {
        this.accepts = new ArrayList<>(accepts);
    }

    ClusterContext getClusterContext() {
        return clusterContext;
    }

    void setClusterContext(ClusterContext clusterContext) {
        this.clusterContext = clusterContext;
    }

    public void setTransportFactory(TransportFactory transportFactory) {
        this.transportFactory = transportFactory;
    }

    @Override
    protected void doExceptionCaught(HttpAcceptSession session, Throwable cause) throws Exception {
        // trigger sessionClosed to update connection capabilities accordingly
        session.close(true);
    }

    @Override
    protected void doSessionOpened(HttpAcceptSession session) throws Exception {
        List availableBalanceeURIs = getBalanceeURIs(session.isSecure());

        if (availableBalanceeURIs.isEmpty()) {
            GL.debug("ha", "Rejected {} request for URI \"{}\" on session {}: no available balancee URI was found",
                        session.getMethod(), session.getRequestURI(), session);
            session.setStatus(HttpStatus.CLIENT_NOT_FOUND);
        } else {

            URI selectedBalanceeURI = availableBalanceeURIs.get((int) (Math.random() * availableBalanceeURIs.size()));
            GL.info("ha", "Selected Balancee URI: {}", selectedBalanceeURI);

            URI requestURI = session.getRequestURI();
            String balanceeScheme = selectedBalanceeURI.getScheme();
            if (balanceeScheme.equals("sse")) {
            	balanceeScheme = "http";
            }
            else if (balanceeScheme.equals("sse+ssl")) {
            	balanceeScheme = "https";
            }
            else {
            	balanceeScheme = selectedBalanceeURI.getScheme().replaceFirst("^ws", "http");
            }
            String balanceePath = selectedBalanceeURI.getPath();
            String requestPath = requestURI.getPath();
            int emIndex = (requestPath != null) ? requestPath.indexOf(WsebAcceptor.EMULATED_SUFFIX) : -1;
            if ((emIndex != -1) && (requestPath.indexOf(WsebAcceptor.EMULATED_SUFFIX + "/cookies") == -1)) {
                balanceePath += requestPath.substring(emIndex);
            }
            String balanceeQuery = requestURI.getQuery();

            // GL.warn("ha", "Selected Balancee Query String: {}", balanceeQuery);

            selectedBalanceeURI = new URI(balanceeScheme, selectedBalanceeURI.getAuthority(), balanceePath, balanceeQuery, null);

            session.setStatus(HttpStatus.REDIRECT_FOUND /* 302 */);
            session.setWriteHeader("Location", selectedBalanceeURI.toString());
        }
        session.close(false);
    }

    List getBalanceeURIs(boolean secure) {
        List balanceeURIs = new ArrayList<>();

        CollectionsFactory collectionsFactory = null;
        if (clusterContext != null) {
            collectionsFactory = clusterContext.getCollectionsFactory();
        }

        if (accepts != null &&
            collectionsFactory != null) {

            Lock mapLock = getLock(HttpBalancerService.MEMBERID_BALANCER_MAP_NAME);
            try {
                mapLock.lock();
                // Get the map of balance URIs to accept URIs from the cluster.
                Map> balancers = collectionsFactory.getMap(HttpBalancerService.BALANCER_MAP_NAME);

                // For my accept URIs, look up the map to get the balancee URIs for which I am balancing.
                for (URI balancerAccept : accepts) {
                    Collection balanceesForAccept = balancers.get(balancerAccept);
                    GL.debug("ha", String.format("Found balancee URIs %s for accept URI %s", balanceesForAccept, balancerAccept));

                    if (balanceesForAccept != null) {
                        for (URI balanceeURI : balanceesForAccept) {
                            // Pick only clear or secure balancees as appropriate.
                            Protocol protocol = transportFactory.getProtocol(balanceeURI);
                            if (secure == protocol.isSecure()) {
                                balanceeURIs.add(balanceeURI);
                            }
                        }
                    }
                }
            } finally {
                mapLock.unlock();
            }

        } else {
            StringBuilder sb = new StringBuilder();
            sb.append("Returning empty balancee URIs list: ");

            if (accepts == null) {
                sb.append("accepts are null, ");
            }

            if (clusterContext.getCollectionsFactory() == null) {
                sb.append("cluster context collections factory is null");
            }

            GL.info("ha", sb.toString());
        }

        return balanceeURIs;
    }


    public Lock getLock(Object obj) {
        return clusterContext.getLock(obj);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy