org.wso2.carbon.event.input.adaptor.websocket.WebsocketEventAdaptorType.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.event.input.adaptor.websocket.WebsocketEventAdaptorType.java

Source

/*
*  Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. 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.wso2.carbon.event.input.adaptor.websocket;

import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.glassfish.tyrus.client.ClientManager;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.event.input.adaptor.core.AbstractInputEventAdaptor;
import org.wso2.carbon.event.input.adaptor.core.InputEventAdaptorListener;
import org.wso2.carbon.event.input.adaptor.core.MessageType;
import org.wso2.carbon.event.input.adaptor.core.Property;
import org.wso2.carbon.event.input.adaptor.core.config.InputEventAdaptorConfiguration;
import org.wso2.carbon.event.input.adaptor.core.exception.InputEventAdaptorEventProcessingException;
import org.wso2.carbon.event.input.adaptor.core.message.config.InputEventAdaptorMessageConfiguration;
import org.wso2.carbon.event.input.adaptor.websocket.internal.WebsocketClient;
import org.wso2.carbon.event.input.adaptor.websocket.internal.util.WebsocketEventAdaptorConstants;

import java.io.IOException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.websocket.*;

public final class WebsocketEventAdaptorType extends AbstractInputEventAdaptor {

    private static WebsocketEventAdaptorType websocketEventAdaptor = new WebsocketEventAdaptorType();
    private ResourceBundle resourceBundle;

    public static ConcurrentHashMap<Integer, ConcurrentHashMap<String, ConcurrentHashMap<String, CopyOnWriteArrayList<ClientManagerWrapper>>>> inputEventAdaptorClientManagerMap = new ConcurrentHashMap<Integer, ConcurrentHashMap<String, ConcurrentHashMap<String, CopyOnWriteArrayList<ClientManagerWrapper>>>>();

    private static Log log = LogFactory.getLog(WebsocketEventAdaptorType.class);

    /**
     * @return Websocket event adaptor instance
     */
    public static WebsocketEventAdaptorType getInstance() {
        return websocketEventAdaptor;
    }

    @Override
    protected String getName() {
        return WebsocketEventAdaptorConstants.ADAPTOR_TYPE_WEBSOCKET;
    }

    @Override
    protected List<String> getSupportedInputMessageTypes() {
        List<String> supportInputMessageTypes = new ArrayList<String>();
        supportInputMessageTypes.add(MessageType.XML);
        supportInputMessageTypes.add(MessageType.JSON);
        supportInputMessageTypes.add(MessageType.TEXT);

        return supportInputMessageTypes;
    }

    @Override
    protected void init() {
        resourceBundle = ResourceBundle.getBundle("org.wso2.carbon.event.input.adaptor.websocket.i18n.Resources",
                Locale.getDefault());
    }

    @Override
    protected List<Property> getInputAdaptorProperties() {
        List<Property> propertyList = new ArrayList<Property>();
        Property urlProperty = new Property(WebsocketEventAdaptorConstants.ADAPTER_SERVER_URL);
        urlProperty.setDisplayName(resourceBundle.getString(WebsocketEventAdaptorConstants.ADAPTER_SERVER_URL));
        urlProperty.setHint(resourceBundle.getString(WebsocketEventAdaptorConstants.ADAPTER_SERVER_URL_HINT));
        urlProperty.setRequired(true);
        propertyList.add(urlProperty);
        return propertyList;
    }

    @Override
    protected List<Property> getInputMessageProperties() {
        List<Property> propertyList = new ArrayList<Property>();

        Property topicProperty = new Property(WebsocketEventAdaptorConstants.ADAPTOR_MESSAGE_TOPIC);
        topicProperty
                .setDisplayName(resourceBundle.getString(WebsocketEventAdaptorConstants.ADAPTOR_MESSAGE_TOPIC));
        topicProperty.setRequired(false);
        topicProperty.setHint(resourceBundle.getString(WebsocketEventAdaptorConstants.ADAPTER_TOPIC_HINT));
        propertyList.add(topicProperty);
        return propertyList;
    }

    @Override
    public String subscribe(InputEventAdaptorMessageConfiguration inputEventAdaptorMessageConfiguration,
            InputEventAdaptorListener inputEventAdaptorListener,
            InputEventAdaptorConfiguration inputEventAdaptorConfiguration, AxisConfiguration axisConfiguration) {

        String subscriptionId = UUID.randomUUID().toString();

        int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
        String topic = inputEventAdaptorMessageConfiguration.getInputMessageProperties()
                .get(WebsocketEventAdaptorConstants.ADAPTOR_MESSAGE_TOPIC);
        String socketServerUrl = inputEventAdaptorConfiguration.getInputProperties()
                .get(WebsocketEventAdaptorConstants.ADAPTER_SERVER_URL);

        if (!socketServerUrl.startsWith("ws://")) {
            throw new InputEventAdaptorEventProcessingException(
                    "Provided websocket URL " + socketServerUrl + " is invalid."); //TODO: Make this exception propagate to the UI.
        }

        if (topic != null) {
            socketServerUrl = socketServerUrl + "/" + topic;
        } else {
            topic = ""; //Using empty string to map the cases with no topic, because topic is optional
        }
        ConcurrentHashMap<String, ConcurrentHashMap<String, CopyOnWriteArrayList<ClientManagerWrapper>>> tenantSpecificAdaptorMap = inputEventAdaptorClientManagerMap
                .get(tenantId);
        if (tenantSpecificAdaptorMap == null) {
            tenantSpecificAdaptorMap = new ConcurrentHashMap<String, ConcurrentHashMap<String, CopyOnWriteArrayList<ClientManagerWrapper>>>();
            if (null != inputEventAdaptorClientManagerMap.putIfAbsent(tenantId, tenantSpecificAdaptorMap)) {
                tenantSpecificAdaptorMap = inputEventAdaptorClientManagerMap.get(tenantId);
            }
        }

        ConcurrentHashMap<String, CopyOnWriteArrayList<ClientManagerWrapper>> adaptorSpecificTopicMap = tenantSpecificAdaptorMap
                .get(inputEventAdaptorConfiguration.getName());

        if (adaptorSpecificTopicMap == null) {
            adaptorSpecificTopicMap = new ConcurrentHashMap<String, CopyOnWriteArrayList<ClientManagerWrapper>>();
            if (null != tenantSpecificAdaptorMap.put(inputEventAdaptorConfiguration.getName(),
                    adaptorSpecificTopicMap)) {
                adaptorSpecificTopicMap = tenantSpecificAdaptorMap.get(inputEventAdaptorConfiguration.getName());
            }
        }

        CopyOnWriteArrayList<ClientManagerWrapper> topicSpecificClientManagers = adaptorSpecificTopicMap.get(topic);
        if (topicSpecificClientManagers == null) {
            topicSpecificClientManagers = new CopyOnWriteArrayList<ClientManagerWrapper>();
            if (null != adaptorSpecificTopicMap.putIfAbsent(topic, topicSpecificClientManagers)) {
                topicSpecificClientManagers = adaptorSpecificTopicMap.get(topic);
            }
        }

        ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create().build();
        ClientManager client = ClientManager.createClient();
        ClientManagerWrapper clientManagerWrapper = new ClientManagerWrapper();
        clientManagerWrapper.setClientManager(client);
        clientManagerWrapper.setSubscriptionId(subscriptionId);
        try {
            client.connectToServer(new WebsocketClient(inputEventAdaptorListener), clientEndpointConfig,
                    new URI(socketServerUrl)); //TODO: Handle reconnecting, in case server disconnects. Suggestion: Create a scheduler.
            topicSpecificClientManagers.add(clientManagerWrapper);
        } catch (DeploymentException e) {
            throw new InputEventAdaptorEventProcessingException(e); //TODO: These exceptions might get modified into new types, as these do not propagate to the UI.
        } catch (IOException e) {
            throw new InputEventAdaptorEventProcessingException(e);
        } catch (Throwable e) {
            throw new InputEventAdaptorEventProcessingException(e);
        }
        return subscriptionId;
    }

    @Override
    public void unsubscribe(InputEventAdaptorMessageConfiguration inputEventAdaptorMessageConfiguration,
            InputEventAdaptorConfiguration inputEventAdaptorConfiguration, AxisConfiguration axisConfiguration,
            String subscriptionId) {
        int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
        String topic = inputEventAdaptorMessageConfiguration.getInputMessageProperties()
                .get(WebsocketEventAdaptorConstants.ADAPTOR_MESSAGE_TOPIC);
        String socketServerUrl = inputEventAdaptorConfiguration.getInputProperties()
                .get(WebsocketEventAdaptorConstants.ADAPTER_SERVER_URL);

        Map<String, ConcurrentHashMap<String, CopyOnWriteArrayList<ClientManagerWrapper>>> tenantSpecificAdaptorMap = inputEventAdaptorClientManagerMap
                .get(tenantId);
        if (tenantSpecificAdaptorMap != null) {
            ConcurrentHashMap<String, CopyOnWriteArrayList<ClientManagerWrapper>> adaptorSpecificTopicMap = tenantSpecificAdaptorMap
                    .get(inputEventAdaptorConfiguration.getName());

            if (adaptorSpecificTopicMap != null) {
                CopyOnWriteArrayList<ClientManagerWrapper> topicSpecificClientManagers = adaptorSpecificTopicMap
                        .get(topic);
                if (topicSpecificClientManagers != null) {
                    for (Iterator<ClientManagerWrapper> iterator = topicSpecificClientManagers.iterator(); iterator
                            .hasNext();) {
                        ClientManagerWrapper clientManagerWrapper = iterator.next();
                        if (subscriptionId.equals(clientManagerWrapper.getSubscriptionId())) {
                            iterator.remove();
                            break;
                        }
                    }
                }
            }
        }
    }

    private class ClientManagerWrapper {
        String subscriptionId;
        ClientManager clientManager;

        public String getSubscriptionId() {
            return subscriptionId;
        }

        public void setSubscriptionId(String subscriptionId) {
            this.subscriptionId = subscriptionId;
        }

        public void setClientManager(ClientManager clientManager) {
            this.clientManager = clientManager;
        }
    }
}