org.wso2.carbon.databridge.agent.thrift.DataPublisher.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.databridge.agent.thrift.DataPublisher.java

Source

/*
 * 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.wso2.carbon.databridge.agent.thrift;

import com.google.gson.Gson;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.databridge.agent.thrift.conf.DataPublisherConfiguration;
import org.wso2.carbon.databridge.agent.thrift.conf.ReceiverConfiguration;
import org.wso2.carbon.databridge.agent.thrift.exception.AgentException;
import org.wso2.carbon.databridge.agent.thrift.internal.EventQueue;
import org.wso2.carbon.databridge.agent.thrift.internal.publisher.client.EventPublisher;
import org.wso2.carbon.databridge.agent.thrift.internal.publisher.client.EventPublisherFactory;
import org.wso2.carbon.databridge.agent.thrift.internal.utils.AgentServerURL;
import org.wso2.carbon.databridge.agent.thrift.lb.ReceiverStateObserver;
import org.wso2.carbon.databridge.commons.Event;
import org.wso2.carbon.databridge.commons.StreamDefinition;
import org.wso2.carbon.databridge.commons.exception.*;
import org.wso2.carbon.databridge.commons.thrift.utils.CommonThriftConstants;
import org.wso2.carbon.databridge.commons.thrift.utils.HostAddressFinder;

import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.util.Map;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Publisher will maintain a single connection to a server,
 * and define/find event streams and send events.
 */
public class DataPublisher {

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

    private static Log log = LogFactory.getLog(DataPublisher.class);
    //    private Agent agent;
    private DataPublisherConfiguration dataPublisherConfiguration;
    private EventPublisher eventPublisher;
    private EventQueue<Event> eventQueue;
    private Gson gson = new Gson();

    private ThreadPoolExecutor threadPool;

    private ReceiverStateObserver receiverStateObserver;

    /**
     * To create the Data Publisher and the respective agent to publish events
     * For TCP protocol
     * For secure data transfer the Authenticator URL will be the same as the Receiver URL and
     * for normal data transfer the Authenticator ip will be the same as receiver ip but its port will be 100+<receiver port> for tcp
     * For HTTP protocol
     * For secure data transfer the Authenticator URL will be the same as the Receiver URL and
     * normal data transfer NOT supported via this constructor
     *
     * @param receiverUrl the event receiver url
     *                    use <tcp>://<HOST>:<PORT> for normal data transfer and
     *                    use <ssl/https>://<HOST>:<PORT> for secure data transfer
     * @param userName    user name
     * @param password    password
     * @throws java.net.MalformedURLException
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.AuthenticationException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.TransportException
     *
     */
    public DataPublisher(String receiverUrl, String userName, String password)
            throws MalformedURLException, AgentException, AuthenticationException, TransportException {
        this(receiverUrl, userName, password, AgentHolder.getOrCreateAgent());
    }

    /**
     * To create the Data Publisher and the respective agent to publish events
     *
     * @param authenticationUrl the secure authentication url, use <ssl/https>://<HOST>:<PORT>
     * @param receiverUrl       the event receiver url
     *                          use <tcp/http></tcp/http>://<HOST>:<PORT> for normal data transfer and
     *                          use <ssl/https></ssl/https>://<HOST>:<PORT> for secure data transfer
     * @param userName          user name
     * @param password          password
     * @throws java.net.MalformedURLException
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.AuthenticationException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.TransportException
     *
     */
    public DataPublisher(String authenticationUrl, String receiverUrl, String userName, String password)
            throws MalformedURLException, AgentException, AuthenticationException, TransportException {
        this(authenticationUrl, receiverUrl, userName, password, AgentHolder.getOrCreateAgent());
    }

    /**
     * To create the Data Publisher to publish events
     * For TCP protocol
     * For secure data transfer the Authenticator URL will be the same as the Receiver URL and
     * for normal data transfer the Authenticator ip will be the same as receiver ip but its port will be 100+<receiver port> for tcp
     * For HTTP protocol
     * For secure data transfer the Authenticator URL will be the same as the Receiver URL and
     * normal data transfer NOT supported via this constructor
     *
     * @param receiverUrl the event receiver url
     *                    use <tcp>://<HOST>:<PORT> for normal data transfer and
     *                    use <ssl/https>://<HOST>:<PORT> for secure data transfer
     * @param userName    user name
     * @param password    password
     * @param agent       the underlining agent
     * @throws java.net.MalformedURLException
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.AuthenticationException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.TransportException
     *
     */
    public DataPublisher(String receiverUrl, String userName, String password, Agent agent)
            throws MalformedURLException, AgentException, AuthenticationException, TransportException {
        /**
         * Only if the agent is not null, then the agent will be set to agent holder.
         * Ie, only for the first datapublisher which is setting the agent,
         * will be actually used and the rest of the agents passed-in will be neglected.
         */
        if (null == agent) {
            agent = AgentHolder.getOrCreateAgent();
        } else if (AgentHolder.getAgent() == null) {
            AgentHolder.setAgent(agent);
        }
        AgentServerURL receiverURL = new AgentServerURL(receiverUrl);
        checkHostAddress(receiverURL.getHost());
        if (receiverURL.isSecured()) {
            this.start(
                    new ReceiverConfiguration(userName, password, receiverURL.getProtocol(),
                            (receiverURL.getHost()), receiverURL.getPort(), receiverURL.getProtocol(),
                            (receiverURL.getHost()), receiverURL.getPort(), receiverURL.isSecured()),
                    AgentHolder.getAgent());
        } else if (receiverURL.getProtocol() == ReceiverConfiguration.Protocol.TCP) {
            this.start(new ReceiverConfiguration(userName, password, receiverURL.getProtocol(),
                    (receiverURL.getHost()), receiverURL.getPort(), receiverURL.getProtocol(),
                    (receiverURL.getHost()),
                    receiverURL.getPort() + CommonThriftConstants.SECURE_EVENT_RECEIVER_PORT_OFFSET,
                    receiverURL.isSecured()), AgentHolder.getAgent());
        } else {
            throw new AgentException("http not supported via this constructor use https, ssl or tcp ");
        }

    }

    /**
     * To create the Data Publisher and the respective agent to publish events
     *
     * @param authenticationUrl the secure authentication url, use <ssl/https>://<HOST>:<PORT>
     * @param receiverUrl       the event receiver url
     *                          use <tcp/http></tcp/http>://<HOST>:<PORT> for normal data transfer and
     *                          use <ssl/https></ssl/https>://<HOST>:<PORT> for secure data transfer
     * @param userName          user name
     * @param password          password
     * @param agent             the underlining agent
     * @throws java.net.MalformedURLException
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.AuthenticationException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.TransportException
     *
     */
    public DataPublisher(String authenticationUrl, String receiverUrl, String userName, String password,
            Agent agent) throws MalformedURLException, AgentException, AuthenticationException, TransportException {
        /**
         * Only if the agent is not null, then the agent will be set to agent holder.
         * Ie, only for the first datapublisher which is setting the agent,
         * will be actually used and the rest of the agents passed-in will be neglected.
         */
        if (null == agent) {
            agent = AgentHolder.getOrCreateAgent();
        } else if (AgentHolder.getAgent() == null) {
            AgentHolder.setAgent(agent);
        }
        AgentServerURL authenticationURL = new AgentServerURL(authenticationUrl);
        if (!authenticationURL.isSecured()) {
            throw new MalformedURLException(
                    "Authentication url protocol is not ssl/https, expected = <ssl/https>://<HOST>:<PORT> but actual = "
                            + authenticationUrl);
        }
        AgentServerURL receiverURL = new AgentServerURL(receiverUrl);
        checkHostAddress(receiverURL.getHost());
        checkHostAddress(authenticationURL.getHost());
        this.start(new ReceiverConfiguration(userName, password, receiverURL.getProtocol(), receiverURL.getHost(),
                receiverURL.getPort(), authenticationURL.getProtocol(), authenticationURL.getHost(),
                authenticationURL.getPort(), receiverURL.isSecured()), AgentHolder.getAgent());

    }

    private void checkHostAddress(String hostAddress) throws AgentException {
        try {
            HostAddressFinder.findAddress(hostAddress);
        } catch (SocketException e) {
            throw new AgentException(hostAddress + " is malformed ", e);
        }
    }

    /**
     * to set the underlining agent
     * which could be sheared by many data publishers
     *
     * @param agent the underlining agent
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.AuthenticationException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.TransportException
     *
     */
    public void setAgent(Agent agent) throws AgentException, AuthenticationException, TransportException {
        AgentHolder.getAgent().shutdown(this);// to shutdown the old agent
        AgentHolder.setAgent(agent);
        start(this.dataPublisherConfiguration.getReceiverConfiguration(), agent);
        if (null != this.receiverStateObserver)
            eventPublisher.registerReceiverStateObserver(receiverStateObserver);
    }

    /**
     * to get the underlining agent
     *
     * @return agent
     */
    public Agent getAgent() {
        return AgentHolder.getAgent();
    }

    public void registerReceiverStateObserver(ReceiverStateObserver stateObserver) {
        this.receiverStateObserver = stateObserver;
        this.eventPublisher.registerReceiverStateObserver(receiverStateObserver);
    }

    private void start(ReceiverConfiguration receiverConfiguration, Agent agent)
            throws AgentException, AuthenticationException, TransportException {
        agent.addDataPublisher(this);
        this.dataPublisherConfiguration = new DataPublisherConfiguration(receiverConfiguration);
        this.eventQueue = new EventQueue<Event>();
        this.threadPool = agent.getThreadPool();
        if (receiverConfiguration.isDataTransferSecured()) {
            this.eventPublisher = EventPublisherFactory.getEventPublisher(dataPublisherConfiguration, eventQueue,
                    agent, agent.getSecureTransportPool());
        } else {
            this.eventPublisher = EventPublisherFactory.getEventPublisher(dataPublisherConfiguration, eventQueue,
                    agent, agent.getTransportPool());
        }
        //Connect to the server
        dataPublisherConfiguration.setSessionId(agent.getAgentAuthenticator().connect(dataPublisherConfiguration));
    }

    /**
     * Defining stream on which events will be published by this DataPublisher
     *
     * @param streamDefinition on json format
     * @return the stream id
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.DifferentStreamDefinitionAlreadyDefinedException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.MalformedStreamDefinitionException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.StreamDefinitionException
     *
     */
    public String defineStream(String streamDefinition) throws AgentException, MalformedStreamDefinitionException,
            StreamDefinitionException, DifferentStreamDefinitionAlreadyDefinedException {
        String sessionId = dataPublisherConfiguration.getSessionId();
        return eventPublisher.defineStream(sessionId, streamDefinition);
    }

    /**
     * Defining stream on which events will be published by this DataPublisher
     *
     * @param streamDefinition on json format
     * @return the stream id
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.DifferentStreamDefinitionAlreadyDefinedException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.MalformedStreamDefinitionException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.StreamDefinitionException
     *
     */
    public String defineStream(StreamDefinition streamDefinition)
            throws AgentException, MalformedStreamDefinitionException, StreamDefinitionException,
            DifferentStreamDefinitionAlreadyDefinedException {
        String sessionId = dataPublisherConfiguration.getSessionId();
        String streamId = eventPublisher.defineStream(sessionId, gson.toJson(streamDefinition));
        try {
            Field field = StreamDefinition.class.getDeclaredField("streamId");
            field.setAccessible(true);
            field.set(streamDefinition, streamId);
        } catch (NoSuchFieldException e) {

        } catch (IllegalAccessException e) {

        }
        return streamId;
    }

    /**
     * Finding already existing stream's Id to publish data
     *
     * @param name    the stream name
     * @param version the version of the stream
     * @return stream id
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *          if client cannot publish the type definition
     */
    @Deprecated
    public String findStream(String name, String version)
            throws AgentException, StreamDefinitionException, NoStreamDefinitionExistException {
        String streamId = findStreamId(name, version);
        if (streamId == null) {
            throw new NoStreamDefinitionExistException("Cannot find Stream Id for " + name + " " + version);
        }
        return streamId;
    }

    /**
        * Finding already existing stream's Id to publish data
        *
        * @param name    the stream name
        * @param version the version of the stream
        * @return stream id
        * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
        *          if client cannot publish the type definition
        */
    public String findStreamId(String name, String version) throws AgentException {
        String sessionId = dataPublisherConfiguration.getSessionId();
        return eventPublisher.findStreamId(sessionId, name, version);
    }

    /**
     * Defining stream on which events will be published by this DataPublisher
     *
     * @param streamId of the Stream
     * @return the stream id
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.DifferentStreamDefinitionAlreadyDefinedException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.MalformedStreamDefinitionException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.StreamDefinitionException
     *
     */
    public boolean deleteStream(String streamId) throws AgentException {
        String sessionId = dataPublisherConfiguration.getSessionId();
        return eventPublisher.deleteStream(sessionId, streamId);
    }

    /**
     * Defining stream on which events will be published by this DataPublisher
     *
     * @param streamName    of the Stream
     * @param streamVersion of the Stream
     * @return the stream id
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.DifferentStreamDefinitionAlreadyDefinedException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.MalformedStreamDefinitionException
     *
     * @throws org.wso2.carbon.databridge.commons.exception.StreamDefinitionException
     *
     */
    public boolean deleteStream(String streamName, String streamVersion) throws AgentException {
        String sessionId = dataPublisherConfiguration.getSessionId();
        return eventPublisher.deleteStream(sessionId, streamName, streamVersion);
    }

    /**
     * Publishing the events to the server
     *
     * @param event the event to be published
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *          if client cannot publish the event
     */
    public void publish(Event event) throws AgentException {
        try {
            AgentHolder.getAgent().getQueueSemaphore().acquire();//control the total number of buffered events

            //Adds event to the queue and checks whether its scheduled for event dispatching
            if (!eventQueue.put(event)) {
                try {
                    //if not schedule for event dispatching
                    threadPool.execute(eventPublisher);
                } catch (RejectedExecutionException ignored) {
                }
            }
        } catch (InterruptedException e) {
            throw new AgentException("Cannot add " + event + " to event queue", e);
        }
    }

    public boolean tryPublish(Event event) throws AgentException {
        try {
            if (AgentHolder.getAgent().getQueueSemaphore().tryAcquire()) {//control the total number of buffered events
                //Adds event to the queue and checks whether its scheduled for event dispatching
                short status = eventQueue.tryPut(event);
                switch (status) {
                case 0:
                    try {
                        //if not schedule for event dispatching
                        threadPool.execute(eventPublisher);
                    } catch (RejectedExecutionException ignored) {
                    }
                    return true;
                case 1:
                    return true;
                case 2:
                    return false;
                default:
                    return false;
                }
            } else {
                return false;
            }
        } catch (InterruptedException e) {
            throw new AgentException("Cannot add " + event + " to event queue", e);
        }
    }

    /**
     * Publishing events to the server
     *
     * @param streamId             of the stream on which the events are published
     * @param metaDataArray        metadata array of the event
     * @param correlationDataArray correlation data array of the event
     * @param payloadDataArray     payload data array of the event
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     */
    public void publish(String streamId, Object[] metaDataArray, Object[] correlationDataArray,
            Object[] payloadDataArray) throws AgentException {
        publish(new Event(streamId, System.currentTimeMillis(), metaDataArray, correlationDataArray,
                payloadDataArray));
    }

    public boolean tryPublish(String streamId, Object[] metaDataArray, Object[] correlationDataArray,
            Object[] payloadDataArray, Map<String, String> arbitraryDataMap) throws AgentException {
        return tryPublish(new Event(streamId, System.currentTimeMillis(), metaDataArray, correlationDataArray,
                payloadDataArray, arbitraryDataMap));
    }

    public boolean tryPublish(String streamId, long timestamp, Object[] metaDataArray,
            Object[] correlationDataArray, Object[] payloadDataArray, Map<String, String> arbitraryDataMap)
            throws AgentException {
        return tryPublish(new Event(streamId, timestamp, metaDataArray, correlationDataArray, payloadDataArray,
                arbitraryDataMap));
    }

    /**
     * Publishing events to the server
     *
     * @param streamId             of the stream on which the events are published
     * @param metaDataArray        metadata array of the event
     * @param correlationDataArray correlation data array of the event
     * @param payloadDataArray     payload data array of the event
     * @param arbitraryDataMap     arbitrary mata (as meta.<key_name>),correlation (as correlation.<key_name>) & payload (as <key_name>) data as key-value pairs
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     */
    public void publish(String streamId, Object[] metaDataArray, Object[] correlationDataArray,
            Object[] payloadDataArray, Map<String, String> arbitraryDataMap) throws AgentException {
        publish(new Event(streamId, System.currentTimeMillis(), metaDataArray, correlationDataArray,
                payloadDataArray, arbitraryDataMap));
    }

    /**
     * Publishing events to the server
     *
     * @param streamId             of the stream on which the events are published
     * @param timeStamp            time stamp of the event
     * @param metaDataArray        metadata array of the event
     * @param correlationDataArray correlation data array of the event
     * @param payloadDataArray     payload data array of the event
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     */
    public void publish(String streamId, long timeStamp, Object[] metaDataArray, Object[] correlationDataArray,
            Object[] payloadDataArray) throws AgentException {
        publish(new Event(streamId, timeStamp, metaDataArray, correlationDataArray, payloadDataArray));
    }

    /**
     * Publishing events to the server
     *
     * @param streamId             of the stream on which the events are published
     * @param timeStamp            time stamp of the event
     * @param metaDataArray        metadata array of the event
     * @param correlationDataArray correlation data array of the event
     * @param payloadDataArray     payload data array of the event
     * @param arbitraryDataMap     arbitrary mata (as meta.<key_name>),correlation (as correlation.<key_name>) & payload (as <key_name>) data as key-value pairs
     * @throws org.wso2.carbon.databridge.agent.thrift.exception.AgentException
     *
     */
    public void publish(String streamId, long timeStamp, Object[] metaDataArray, Object[] correlationDataArray,
            Object[] payloadDataArray, Map<String, String> arbitraryDataMap) throws AgentException {
        publish(new Event(streamId, timeStamp, metaDataArray, correlationDataArray, payloadDataArray,
                arbitraryDataMap));
    }

    /**
     * Disconnecting from the server
     */
    public void stop() {
        AgentHolder.getAgent().getAgentAuthenticator().disconnect(dataPublisherConfiguration);
        AgentHolder.getAgent().shutdown(this);
    }

    /**
     * Disconnecting from the server
     */
    public void stopNow() {
        AgentHolder.getAgent().getAgentAuthenticator().disconnect(dataPublisherConfiguration);
        AgentHolder.getAgent().shutdownNow(this);
    }

}