org.wso2.carbon.registry.caching.invalidator.connection.JMSNotification.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.registry.caching.invalidator.connection.JMSNotification.java

Source

/*
 * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) 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 org.wso2.carbon.registry.caching.invalidator.connection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.registry.caching.invalidator.impl.ConfigurationManager;
import org.wso2.carbon.registry.caching.invalidator.impl.GlobalCacheInvalidationEvent;
import org.wso2.carbon.registry.caching.invalidator.internal.CacheInvalidationDataHolder;
import org.wso2.carbon.context.PrivilegedCarbonContext;

import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TopicSession;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Properties;

public class JMSNotification implements InvalidNotification, MessageListener {

    // Setup the pub/sub connection, session
    // Send the msg (byte stream)
    private static Connection connection = null;

    private static Destination destination = null;

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

    @Override
    public void createConnection(Properties config) {
        try {
            Properties props = new Properties();
            props.put(Context.INITIAL_CONTEXT_FACTORY, config.getProperty("initialContextFactory"));
            props.put(Context.PROVIDER_URL, config.getProperty("providerUrl"));
            props.put(Context.SECURITY_PRINCIPAL, config.getProperty("securityPrincipal"));
            props.put(Context.SECURITY_CREDENTIALS, config.getProperty("securityCredentials"));
            props.put("topic.cacheInvalidateTopic", config.getProperty("cacheInvalidateTopic"));
            InitialContext jndi = new InitialContext(props);
            ConnectionFactory connectionFactory = (ConnectionFactory) jndi.lookup("ConnectionFactory");
            destination = (Destination) jndi.lookup("cacheInvalidateTopic");

            connection = connectionFactory.createConnection(config.getProperty("securityPrincipal"),
                    config.getProperty("securityCredentials"));
            connection.start();
        } catch (NamingException | JMSException e) {
            log.error("Global cache invalidation: Error message broker initialization", e);
        }
    }

    @Override
    public void closeConnection() {
        if (connection != null) {
            try {
                connection.close();
            } catch (JMSException e) {
                log.error("Global cache invalidation: Error in closing connection", e);
            }
        }
    }

    @Override
    public void publish(Object message) {
        Session pubSession = null;
        try {
            if (connection != null) {
                pubSession = connection.createSession(false, TopicSession.AUTO_ACKNOWLEDGE);
                MessageProducer publisher = pubSession.createProducer(destination);
                BytesMessage bytesMessage = pubSession.createBytesMessage();
                bytesMessage.writeBytes((byte[]) message);
                publisher.send(bytesMessage);
            }
        } catch (JMSException e) {
            log.error("Global cache invalidation: Error in publishing the message", e);
        } finally {
            if (pubSession != null) {
                try {
                    pubSession.close();
                } catch (JMSException e) {
                    log.error("Global cache invalidation: Error in publishing the message", e);
                }
            }
        }
    }

    @Override
    public void subscribe() {
        try {
            Session subSession = connection.createSession(false, TopicSession.AUTO_ACKNOWLEDGE);
            MessageConsumer messageConsumer = subSession.createConsumer(destination);
            messageConsumer.setMessageListener(this);
            connection.start();
            log.info("Global cache invalidation is online");
        } catch (JMSException e) {
            log.error("Global cache invalidation: Error in subscribing to topic", e);
        }
    }

    @Override
    public void onMessage(Message message) {
        BytesMessage bytesMessage = (BytesMessage) message;
        byte[] data;
        try {
            data = new byte[(int) bytesMessage.getBodyLength()];
            for (int i = 0; i < (int) bytesMessage.getBodyLength(); i++) {
                data[i] = bytesMessage.readByte();
            }
            log.debug("Cache invalidation message received: " + new String(data));
        } catch (JMSException jmsException) {
            log.error("Error while reading the received message", jmsException);
            return;
        }

        boolean isCoordinator = false;
        if (CacheInvalidationDataHolder.getConfigContext() != null) {
            isCoordinator = CacheInvalidationDataHolder.getConfigContext().getAxisConfiguration()
                    .getClusteringAgent().isCoordinator();
        }
        if (isCoordinator) {
            PrivilegedCarbonContext.startTenantFlow();
            try {
                log.debug("Global cache invalidation: deserializing data to object");
                GlobalCacheInvalidationEvent event = (GlobalCacheInvalidationEvent) deserialize(data);
                log.debug("Global cache invalidation: deserializing complete");
                if (!ConfigurationManager.getSentMsgBuffer().contains(event.getUuid().trim())) { // Ignore own messages
                    PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(event.getTenantId(), true);
                    CacheManager cacheManager = Caching.getCacheManagerFactory()
                            .getCacheManager(event.getCacheManagerName());
                    if (cacheManager != null) {
                        if (cacheManager.getCache(event.getCacheName()) != null) {
                            cacheManager.getCache(event.getCacheName()).remove(event.getCacheKey());
                            log.debug("Global cache invalidated: " + event.getCacheKey());
                        } else {
                            log.error("Global cache invalidation: error cache is null");
                        }
                    } else {
                        log.error("Global cache invalidation: error cache manager is null");
                    }
                } else {
                    // To resolve future performance issues
                    ConfigurationManager.getSentMsgBuffer().remove(event.getUuid().trim());
                    log.debug("Global cache invalidation: own message ignored");
                }
            } catch (Exception e) {
                log.error("Global cache invalidation: error local cache update", e);
            } finally {
                PrivilegedCarbonContext.endTenantFlow();
            }
        }
    }

    private Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        return objectInputStream.readObject();
    }
}