
org.richfaces.push.JMSTopicsContextImpl Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.richfaces.push;
import static org.richfaces.configuration.CoreConfiguration.Items.pushJMSConnectionFactory;
import static org.richfaces.configuration.CoreConfiguration.Items.pushJMSConnectionPassword;
import static org.richfaces.configuration.CoreConfiguration.Items.pushJMSConnectionPasswordEnvRef;
import static org.richfaces.configuration.CoreConfiguration.Items.pushJMSConnectionUsername;
import static org.richfaces.configuration.CoreConfiguration.Items.pushJMSConnectionUsernameEnvRef;
import static org.richfaces.configuration.CoreConfiguration.Items.pushJMSTopicsNamespace;
import static org.richfaces.configuration.CoreConfiguration.PushPropertiesItems.pushPropertiesJMSConnectionFactory;
import static org.richfaces.configuration.CoreConfiguration.PushPropertiesItems.pushPropertiesJMSConnectionPassword;
import static org.richfaces.configuration.CoreConfiguration.PushPropertiesItems.pushPropertiesJMSConnectionUsername;
import static org.richfaces.configuration.CoreConfiguration.PushPropertiesItems.pushPropertiesJMSTopicsNamespace;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadFactory;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NameParser;
import javax.naming.NamingException;
import org.richfaces.configuration.ConfigurationService;
import org.richfaces.javascript.JSLiteral;
import org.richfaces.log.Logger;
import org.richfaces.log.RichfacesLogger;
import org.richfaces.services.ServiceTracker;
import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
* @author Nick Belaevski
*
*/
public class JMSTopicsContextImpl extends TopicsContextImpl {
private static final Logger LOGGER = RichfacesLogger.APPLICATION.getLogger();
private class JMSTopicContext {
/**
*
*/
private static final String SUBTOPIC_PROPERTY = "rf_push_subtopic";
private static final String SERIALIZED_DATA_INDICATOR = "org_richfaces_push_SerializedData";
private final String name;
private Connection connection;
private Session session;
private Thread pollingThread;
private MessageConsumer consumer;
public JMSTopicContext(String name) {
super();
this.name = name;
}
private Topic lookupTopic() throws NamingException {
Name topicName = appendToName(topicsNamespace, name);
return (Topic) initialContext.lookup(topicName);
}
private Connection createConnection() throws JMSException, NamingException {
ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup(connectionFactoryName);
Connection connection = connectionFactory.createConnection(username, password);
connection.start();
return connection;
}
private Object getMessageData(Message message) throws JMSException {
Object messageData = null;
if (message instanceof ObjectMessage) {
messageData = ((ObjectMessage) message).getObject();
} else if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
if (message.getBooleanProperty(SERIALIZED_DATA_INDICATOR)) {
messageData = new JSLiteral(textMessage.getText());
} else {
messageData = textMessage.getText();
}
}
return messageData;
}
public synchronized void start() throws NamingException, JMSException {
connection = createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(lookupTopic(), null, false);
pollingThread = getThreadFactory().newThread(new Runnable() {
public void run() {
try {
while (true) {
Message message = consumer.receive();
if (message != null) {
String subtopicName = message.getStringProperty(SUBTOPIC_PROPERTY);
TopicKey topicKey = new TopicKey(name, subtopicName);
org.richfaces.push.Topic pushTopic = getOrCreateTopic(topicKey);
if (pushTopic != null) {
try {
Object messageData = getMessageData(message);
pushTopic.publish(topicKey, messageData);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
} else {
break;
}
}
} catch (JMSException e) {
LOGGER.error(e.getMessage(), e);
}
}
});
pollingThread.start();
}
public synchronized void stop() {
if (consumer != null) {
try {
consumer.close();
consumer = null;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
if (session != null) {
try {
session.close();
session = null;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
if (connection != null) {
try {
connection.close();
connection = null;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
}
}
private final InitialContext initialContext;
private final Name connectionFactoryName;
private final Name topicsNamespace;
private final String username;
private final String password;
private final LoadingCache contextsCache = CacheBuilder.newBuilder().build(
CacheLoader.from(new Function() {
public JMSTopicContext apply(String name) {
JMSTopicContext topicContext = new JMSTopicContext(name);
try {
topicContext.start();
} catch (Exception e) {
try {
topicContext.stop();
} catch (Exception e1) {
LOGGER.error(e1.getMessage(), e1);
}
throw new FacesException(e.getMessage(), e);
}
return topicContext;
}
}));
public JMSTopicsContextImpl(ThreadFactory threadFactory, InitialContext initialContext, Name connectionFactoryName,
Name topicsNamespace, String username, String password) {
super(threadFactory);
this.initialContext = initialContext;
this.connectionFactoryName = connectionFactoryName;
this.topicsNamespace = topicsNamespace;
this.username = username;
this.password = password;
}
public static JMSTopicsContextImpl getInstanceInitializedFromContext(ThreadFactory threadFactory, FacesContext facesContext)
throws NamingException {
ConfigurationService configurationService = ServiceTracker.getService(ConfigurationService.class);
InitialContext initialContext = new InitialContext();
NameParser nameParser = initialContext.getNameParser("");
Name connectionFactoryName = nameParser.parse(getConnectionFactory(facesContext, configurationService));
Name topicsNamespace = nameParser.parse(getTopicsNamespace(facesContext, configurationService));
String username = getUserName(facesContext, configurationService);
String password = getPassword(facesContext, configurationService);
return new JMSTopicsContextImpl(threadFactory, initialContext, connectionFactoryName, topicsNamespace, username,
password);
}
private static String getConnectionFactory(FacesContext facesContext, ConfigurationService configurationService) {
return getFirstNonEmptyConfgirutationValue(facesContext, configurationService, pushPropertiesJMSConnectionFactory,
pushJMSConnectionFactory);
}
private static String getTopicsNamespace(FacesContext facesContext, ConfigurationService configurationService) {
return getFirstNonEmptyConfgirutationValue(facesContext, configurationService, pushPropertiesJMSTopicsNamespace,
pushJMSTopicsNamespace);
}
private static String getPassword(FacesContext facesContext, ConfigurationService configurationService) {
return getFirstNonEmptyConfgirutationValue(facesContext, configurationService, pushPropertiesJMSConnectionPassword,
pushJMSConnectionPasswordEnvRef, pushJMSConnectionPassword);
}
private static String getUserName(FacesContext facesContext, ConfigurationService configurationService) {
return getFirstNonEmptyConfgirutationValue(facesContext, configurationService, pushPropertiesJMSConnectionUsername,
pushJMSConnectionUsernameEnvRef, pushJMSConnectionUsername);
}
private static String getFirstNonEmptyConfgirutationValue(FacesContext facesContext, ConfigurationService service,
Enum>... keys) {
for (Enum> key : keys) {
String value = service.getStringValue(facesContext, key);
if (!Strings.isNullOrEmpty(value)) {
return value;
}
}
return "";
}
private Name appendToName(Name name, String comp) throws NamingException {
Name clonedName = (Name) name.clone();
return clonedName.add(comp);
}
@Override
protected org.richfaces.push.Topic createTopic(TopicKey key) {
org.richfaces.push.Topic topic = super.createTopic(key);
try {
contextsCache.get(key.getTopicName());
} catch (ExecutionException e) {
throw new FacesException(String.format("Can't create a JMS topic %s", key), e);
}
return topic;
}
@Override
public void destroy() {
for (JMSTopicContext topicContext : contextsCache.asMap().values()) {
try {
topicContext.stop();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
super.destroy();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy