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

edu.internet2.middleware.grouperMessagingActiveMQ.GrouperMessagingActiveMQSystem Maven / Gradle / Ivy

There is a newer version: 5.13.5
Show newest version
/**
 * @author vsachdeva
 * $Id$
 */
package edu.internet2.middleware.grouperMessagingActiveMQ;

import static edu.internet2.middleware.grouperClient.messaging.GrouperMessageQueueType.topic;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import javax.jms.Connection;
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.TextMessage;

import org.apache.qpid.jms.JmsConnectionFactory;

import edu.internet2.middleware.grouper.util.GrouperUtil;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessage;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageAcknowledgeParam;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageAcknowledgeResult;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageQueueParam;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageQueueType;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageReceiveParam;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageReceiveResult;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageSendParam;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageSendResult;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessageSystemParam;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessagingConfig;
import edu.internet2.middleware.grouperClient.messaging.GrouperMessagingSystem;
import edu.internet2.middleware.grouperClient.util.GrouperClientConfig;
import edu.internet2.middleware.grouperClient.util.GrouperClientUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class GrouperMessagingActiveMQSystem implements GrouperMessagingSystem {
   
  /** logger */
  private static final Log LOG = LogFactory.getLog(GrouperMessagingActiveMQSystem.class);
  
  public GrouperMessagingActiveMQSystem() {}
  
  /**
   * @see edu.internet2.middleware.grouperClient.messaging.GrouperMessagingSystem#send(edu.internet2.middleware.grouperClient.messaging.GrouperMessageSendParam)
   */
  public GrouperMessageSendResult send(GrouperMessageSendParam grouperMessageSendParam) {
        
    GrouperMessageSystemParam systemParam = grouperMessageSendParam.getGrouperMessageSystemParam();
    GrouperMessageQueueParam queueParam = grouperMessageSendParam.getGrouperMessageQueueParam();
    
    validate(queueParam, systemParam);
    
    String queueOrTopicName = queueParam.getQueueOrTopicName();
    
    GrouperMessagingConfig grouperMessagingConfig = GrouperClientConfig.retrieveConfig().retrieveGrouperMessagingConfigNonNull(systemParam.getMessageSystemName());

    //Create a single ActiveMQ session per connection, to prevent OOM errors
    boolean createSingleSessionPerConnection = GrouperUtil.booleanValue(grouperMessagingConfig.propertyValueString(GrouperClientConfig.retrieveConfig(), "createSingleSessionPerConnection"), false);
    try {
      Connection connection = ActiveMQClientConnectionFactory.INSTANCE.getActiveMQConnection(systemParam.getMessageSystemName());
      
      // Create a non-transactional session with automatic acknowledgement
      Session session = null;
      
      if (createSingleSessionPerConnection) {
        session = ActiveMQClientConnectionFactory.INSTANCE.getActiveMQSendSession(systemParam.getMessageSystemName());
      } else {
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      }
      
      
      Destination destination = null;
      if (queueParam.getQueueType() == GrouperMessageQueueType.queue) {
        destination = session.createQueue(queueOrTopicName);             
      } else {
        destination = session.createTopic(queueOrTopicName);
      }

      MessageProducer producer = session.createProducer(destination);
      
      for (GrouperMessage grouperMessage: GrouperClientUtils.nonNull(grouperMessageSendParam.getGrouperMessages())) {
        
        TextMessage message = session.createTextMessage (grouperMessage.getMessageBody());
        producer.send(message);
        LOG.info("Sent "+grouperMessage.getMessageBody()+" to ActiveMQ.");
        
      }
    } catch (JMSException e) {
      LOG.error("Error occurred while sending message to messaging system name: "+systemParam.getMessageSystemName(), e);
      try {
        closeConnection(systemParam.getMessageSystemName());
      } catch (Exception ex) {
        // do nothing
      }
      throw new RuntimeException("Error occurred while closing channel for messaging system: "+systemParam.getMessageSystemName(), e);
    }
    
    return new GrouperMessageSendResult();
  }
  
  /**
   * @see edu.internet2.middleware.grouperClient.messaging.GrouperMessagingSystem#acknowledge(edu.internet2.middleware.grouperClient.messaging.GrouperMessageAcknowledgeParam)
   */
  public GrouperMessageAcknowledgeResult acknowledge(GrouperMessageAcknowledgeParam grouperMessageAcknowledgeParam) {
    return new GrouperMessageAcknowledgeResult();
  }

  /**
   * @see edu.internet2.middleware.grouperClient.messaging.GrouperMessagingSystem#receive(edu.internet2.middleware.grouperClient.messaging.GrouperMessageReceiveParam)
   */
  public GrouperMessageReceiveResult receive(GrouperMessageReceiveParam grouperMessageReceiveParam) {
    
    final GrouperMessageSystemParam systemParam = grouperMessageReceiveParam.getGrouperMessageSystemParam();
    final GrouperMessageQueueParam queueParam = grouperMessageReceiveParam.getGrouperMessageQueueParam();
    
    validate(queueParam, systemParam);
    
    GrouperMessagingConfig grouperMessagingConfig = GrouperClientConfig.retrieveConfig().retrieveGrouperMessagingConfigNonNull(systemParam.getMessageSystemName());
    int defaultPageSize = grouperMessagingConfig.propertyValueInt(GrouperClientConfig.retrieveConfig(), "defaultPageSize", 5);
    int maxPageSize = grouperMessagingConfig.propertyValueInt(GrouperClientConfig.retrieveConfig(), "maxPageSize", 10);
    
    Integer maxMessagesToReceiveAtOnce = grouperMessageReceiveParam.getMaxMessagesToReceiveAtOnce();
    
    if (maxMessagesToReceiveAtOnce == null) {
      maxMessagesToReceiveAtOnce = defaultPageSize;
    }
    
    if (maxMessagesToReceiveAtOnce > maxPageSize) {
      maxMessagesToReceiveAtOnce = maxPageSize;
    }
    
    String queueOrTopicName = queueParam.getQueueOrTopicName();
    
    Integer longPollMillis = grouperMessageReceiveParam.getLongPollMilis();
    
    if (longPollMillis == null || longPollMillis < 0) {
      longPollMillis = 1000;
    }
    
    long startReceive = System.currentTimeMillis();
    
    int pollSleepSeconds = grouperMessagingConfig.propertyValueInt(GrouperClientConfig.retrieveConfig(), "polling.sleep.seconds", 5);
    
    if (pollSleepSeconds < 1) {
      pollSleepSeconds = 1;
    }
    GrouperMessageReceiveResult result = new GrouperMessageReceiveResult();
    final Collection messages = new ArrayList();
    result.setGrouperMessages(messages);
    
    try {
      Connection connection = ActiveMQClientConnectionFactory.INSTANCE.getActiveMQConnection(systemParam.getMessageSystemName());
      
      Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
      
      Destination destination = null;
      if (queueParam.getQueueType() == topic) {
        destination = session.createTopic(queueOrTopicName);
      } else {
        destination = session.createQueue(queueOrTopicName);
      }
      
      MessageConsumer consumer = session.createConsumer(destination);
      
      consumer.setMessageListener(new MessageListener() {
        @Override
        public void onMessage(Message message) {
          if (message instanceof TextMessage) {
            String body = null;
            try {
              body = ((TextMessage) message).getText();
              messages.add(new GrouperMessageActiveMQ(body, ((TextMessage) message).getJMSMessageID()));
              message.acknowledge();
            } catch (JMSException e) {
              LOG.error("Error occurred while receiving messages for messaging system name "+systemParam.getMessageSystemName(), e);
            }
          } else {
            LOG.error("Only text messages are allowed with ActiveMQ");
          }
        }
      });
      
      while (true) {
        //dont long poll
        if (longPollMillis < 0) {
          break;
        }
        if (longPollMillis < System.currentTimeMillis() - startReceive ) {
          break;
        }
        GrouperClientUtils.sleep(Math.min(pollSleepSeconds*1000, System.currentTimeMillis() + 20 - startReceive));
      }
      
    } catch(JMSException e) {
      LOG.error("Error occurred while receiving messages for system name "+systemParam.getMessageSystemName(), e);
    }
    
    return result;
  }
  
  private void validate(GrouperMessageQueueParam queueParam, GrouperMessageSystemParam systemParam) {
    
    if (queueParam == null) {
      throw new IllegalArgumentException("grouperMessageQueueParam cannot be null.");
    }
    
    if (systemParam == null) {
      throw new IllegalArgumentException("grouperMessageSystemParam cannot be null.");
    }
    
    if (queueParam.getQueueType() == null) {
      throw new IllegalArgumentException("queueType is a required field.");
    }
    
    String queueName = queueParam.getQueueOrTopicName();
    
    if (StringUtils.isBlank(queueName)) {
      throw new IllegalArgumentException("queueOrTopicName is a required field.");
    }
    
    if (StringUtils.isBlank(systemParam.getMessageSystemName())) {
      throw new IllegalArgumentException("messageSystemName is a required field.");
    }
    
    if (!systemParam.isAutocreateObjects()) {
      throw new IllegalArgumentException("For ActiveMQ, autoCreateObjects has to be set to true.");
    }
    
  }
  
  
  void closeConnection(String messagingSystemName) throws JMSException {
    ActiveMQClientConnectionFactory.INSTANCE.closeConnection(messagingSystemName);
  }
  
  private enum ActiveMQClientConnectionFactory {
    
    INSTANCE;
    
    private Map messagingSystemNameConnection = new HashMap();
           
    private Map messagingSystemNameSession = new HashMap<>();

    private Session getActiveMQSendSession(String messagingSystemName) throws JMSException {
      if (StringUtils.isBlank(messagingSystemName)) {
        throw new IllegalArgumentException("messagingSystemName is required.");
      }

      Connection connection =  messagingSystemNameConnection.get(messagingSystemName);

      if (connection == null) {
        throw new JMSException("Connection does not exist. Create a connection first");
      }

      Session session =  messagingSystemNameSession.get(messagingSystemName);

      if (session == null) {
        synchronized(ActiveMQClientConnectionFactory.class) {
          
          session =  messagingSystemNameSession.get(messagingSystemName);
          
          if (session == null) {

            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            messagingSystemNameSession.put(messagingSystemName,session);
          }
        }
      }

      return session;
    }

    private Connection getActiveMQConnection(String messagingSystemName) throws JMSException {
      
      if (StringUtils.isBlank(messagingSystemName)) {
        throw new IllegalArgumentException("messagingSystemName is required.");
      }
      
      Connection connection =  messagingSystemNameConnection.get(messagingSystemName);
      
      if (connection == null) {
        synchronized(ActiveMQClientConnectionFactory.class) {
          
          connection =  messagingSystemNameConnection.get(messagingSystemName);
          
          if (connection == null) {
            
            GrouperMessagingConfig grouperMessagingConfig = GrouperClientConfig.retrieveConfig().retrieveGrouperMessagingConfigNonNull(messagingSystemName);
  
            String host = grouperMessagingConfig.propertyValueString(GrouperClientConfig.retrieveConfig(), "host");
            String uri =  grouperMessagingConfig.propertyValueString(GrouperClientConfig.retrieveConfig(), "uri");
            String username = grouperMessagingConfig.propertyValueString(GrouperClientConfig.retrieveConfig(), "username");
            String password = grouperMessagingConfig.propertyValueString(GrouperClientConfig.retrieveConfig(), "password");
            
            if (StringUtils.isNotBlank(password)) {
              password = GrouperClientUtils.decryptFromFileIfFileExists(password, null);
            }
            Integer port = grouperMessagingConfig.propertyValueInt(GrouperClientConfig.retrieveConfig(), "port", -1);
  
            String connectionUrl;
            if (StringUtils.isNotBlank(uri)) {
              connectionUrl = uri;
            } else {
              connectionUrl = "amqp://"+host+":"+port;
            }
  
            JmsConnectionFactory factory = new JmsConnectionFactory(connectionUrl);
            if (StringUtils.isNotBlank(username)) {
              factory.setUsername(username);
            }
            if (StringUtils.isNotBlank(password)) {
              factory.setPassword(password);
            }
            
            connection = factory.createConnection();
            connection.start();
            messagingSystemNameConnection.put(messagingSystemName, connection);
              
          }
        }
      }
      return connection;
    }
    
    private void closeConnection(String messagingSystemName) throws JMSException {
      if (StringUtils.isBlank(messagingSystemName)) {
        throw new IllegalArgumentException("messagingSystemName is required.");
      }
      Connection connection = messagingSystemNameConnection.get(messagingSystemName);
      synchronized(ActiveMQClientConnectionFactory.class) {
        if (connection != null) {
          try {
            connection.stop();
          } catch(Exception e) {
            throw new RuntimeException("Error occurred while closing ActiveMQ connection for "+messagingSystemName, e);
          } finally {
            messagingSystemNameConnection.remove(messagingSystemName);
            messagingSystemNameSession.remove(messagingSystemName);
          }
        }
      }
    }
    
  }
  
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy