# Classes Java usadas nesse arquivo import 'java.util.Hashtable' import 'javax.naming.InitialContext' module JSparrow module Connection # # Metodo usado para configurar a conexao com o middleware de JMS. # def self.configure @@properties = ConnectionProperties.new yield @@properties end # # Metodo usado para obter a configuracao para conexao com o middleware de JMS. # def self.connection_properties @@properties end # # Metodo usado para criar um novo Client JMS. # def self.new_client jndi_context_builder = JNDI::ContextBuilder.new(@@properties.jms_client_jar, @@properties.jndi_properties) Client.new(@@properties, jndi_context_builder) end # # Configuracoes necessarias para que clientes JMS se conetem # ao middleware de mensageria via contexto JNDI. # class ConnectionProperties attr_reader :jms_client_jar, :jndi_properties, :enabled_connection_factories, :enabled_queues, :enabled_topics def use_jms_client_jar(client_jar) @jms_client_jar = client_jar end def use_jndi_properties(jndi_properties = {}) @jndi_properties = jndi_properties end def enable_connection_factories(jndi_names = {}) @enabled_connection_factories = jndi_names end def enable_queues(jndi_names = {}) @enabled_queues = jndi_names end def enable_topics(jndi_names = {}) @enabled_topics = jndi_names end end # # Cliente JMS que possibilita a conexao com o servidor de aplicacoes Java EE # que prove o servico JMS. # class Client def initialize(connection_properties, jndi_context_builder) @connection_properties = connection_properties @jndi_context_builder = jndi_context_builder @jndi_name_of_enabled_connection_factories = @connection_properties.enabled_connection_factories @jndi_name_of_enabled_queues = {} @jndi_name_of_enabled_topics = {} # Conexoes, filas, topicos, senders e receivers que serao habilitados @connection_factories = {} @queues = {} @queue_senders = {} @queue_receivers = {} @topics = {} @topic_senders = {} @topic_receivers = {} # Foi startado? @started = false end def is_started? @started end def start raise InvalidClientStateError.new('started', 'start') if is_started? begin @jndi_context = @jndi_context_builder.build rescue => cause raise ClientInitializationError.new(@connection_properties, cause) end @connection_factories = lookup_resource(@jndi_name_of_enabled_connection_factories) @queues = lookup_resource(@jndi_name_of_enabled_queues) @topics = lookup_resource(@jndi_name_of_enabled_topics) @started = true end def is_stoped? !@started end def stop raise InvalidClientStateError.new('stoped', 'stop') if is_stoped? @jndi_context.close @started = false end def queue_connection_factory_enabled? @jndi_name_of_enabled_connection_factories.include?(:queue_connection_factory) end def queue_connection_factory @connection_factories[:queue_connection_factory] end def topic_connection_factory_enabled? @jndi_name_of_enabled_connection_factories.include?(:topic_connection_factory) end def topic_connection_factory @connection_factories[:topic_connection_factory] end def enable_queues(jndi_names = {}) raise InvalidClientStateError.new('started', 'enable_queues') if is_started? @jndi_name_of_enabled_queues = jndi_names end def queue_enabled?(queue_name) @jndi_name_of_enabled_queues.include?(queue_name) end def queue(queue_name) raise NameError, "Queue '#{queue_name}' does not exist." unless queue_enabled?(queue_name) @queues[queue_name] end def queue_sender(queue_name) @queue_senders[queue_name] ||= Messaging::Sender.new(queue_connection_factory, queue(queue_name)) end def queue_receiver(queue_name) @queue_receivers[queue_name] ||= Messaging::Receiver.new(queue_connection_factory, queue(queue_name)) end def enable_topics(jndi_names = {}) raise InvalidClientStateError.new('started', 'enable_topics') if is_started? @jndi_name_of_enabled_topics = jndi_names end def topic_enabled?(topic_name) @jndi_name_of_enabled_topics.include?(topic_name) end def topic(topic_name) raise NameError, "Topic '#{topic_name}' does not exist." unless topic_enabled?(topic_name) @topics[topic_name] end def topic_sender(topic_name) @topic_senders[topic_name] ||= Messaging::Sender.new(topic_connection_factory, topic(topic_name)) end def topic_receiver(topic_name) @topic_receivers[topic_name] ||= Messaging::Receiver.new(topic_connection_factory, topic(topic_name)) end # -- Private methods -- # private def lookup_resource(jndi_names = {}) lookuped = {} jndi_names.each do |key, jndi_name| lookuped[key] = @jndi_context.lookup(jndi_name) end lookuped end end class ClientInitializationError < StandardError attr_reader :properties, :cause def initialize(properties, cause) super("Could not open connection to server. Verify the properties's properties.") @properties = properties @cause = cause end end class InvalidClientStateError < StandardError attr_reader :state, :operation def initialize(state, operation) super("Could not did #{operation} because client is #{state}.") @state = state @operation = operation end end end module JNDI # # Builder para construcao de contexto JNDI para conexao com o middleware # de JMS. # class ContextBuilder attr_accessor :jms_client_jar, :jndi_properties def initialize(jms_client_jar, jndi_properties) @jms_client_jar = jms_client_jar @jndi_properties = jndi_properties end # # Constroi um contexto JNDI inicial a partir das configuracoes atuais. # def build # Carrega a biblioteca cliente do servidor de aplicacoes require @jms_client_jar InitialContext.new(to_jndi_environment_hashtable) end # --- Private methods --- # private # # Cria um Hashtable Java contendo as configuracoes atuais. # def to_jndi_environment_hashtable jndi_env = Hashtable.new jndi_env.put( InitialContext::INITIAL_CONTEXT_FACTORY, @jndi_properties[:initial_context_factory]) jndi_env.put( InitialContext::PROVIDER_URL, @jndi_properties[:provider_url]) jndi_env.put( InitialContext::SECURITY_PRINCIPAL, @jndi_properties[:security_principal]) if @jndi_properties[:security_principal] jndi_env.put( InitialContext::SECURITY_CREDENTIALS, @jndi_properties[:security_credentials]) if @jndi_properties[:security_credentials] jndi_env end end end end