package com.thoughtworks.winstonwolfe.endpoint;
import com.thoughtworks.winstonwolfe.config.WinstonConfig;
import com.thoughtworks.winstonwolfe.datasource.DataSource;
import com.thoughtworks.winstonwolfe.datasource.StringDataSource;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Properties;
public class JmsServiceEndPoint implements ServiceEndPoint {
private WinstonConfig config;
public JmsServiceEndPoint(WinstonConfig endpointConfig) {
config = endpointConfig;
}
@Override
public DataSource send(DataSource data) throws Exception {
Properties env = getProperties();
InitialContext context = new InitialContext(env);
Connection conn = getConnection(context);
try {
conn.start();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination requestQueue = getRequestQueue(context, session);
Destination responseQueue = getResponseQueue(context, session);
MessageProducer producer = session.createProducer(requestQueue);
BytesMessage requestMessage = sendMessage(data, session, producer, responseQueue);
MessageConsumer consumer = getMessageConsumerUsingCorrelationId(session, responseQueue, requestMessage);
return getResponse(consumer);
} finally {
conn.close();
}
}
private Destination getRequestQueue(InitialContext context, Session session) throws JMSException, NamingException {
if (config.exists("request_queue_type")) {
if (config.getString("request_queue_type") == "dynamic") {
return session.createTemporaryQueue();
}
}
return (Destination) context.lookup(config.getString("request_queue"));
}
private Destination getResponseQueue(InitialContext context, Session session) throws JMSException, NamingException {
if (config.exists("response_queue_type")) {
if (config.getString("response_queue_type") == "dynamic") {
return session.createTemporaryQueue();
}
}
return (Destination) context.lookup(config.getString("response_queue"));
}
private DataSource getResponse(MessageConsumer consumer) throws JMSException, UnsupportedEncodingException {
BytesMessage responseMessage = (BytesMessage) consumer.receive(getTimeout());
if (responseMessage == null) {
throw new RuntimeException("received null response message - probably due to timeout");
}
byte[] bytes = new byte[(int) responseMessage.getBodyLength()];
responseMessage.readBytes(bytes);
return new StringDataSource(new String(bytes, config.getString("encoding")));
}
private Integer getTimeout() {
return config.exists("timeout") ? config.getInt("timeout") : 5000;
}
private MessageConsumer getMessageConsumerUsingCorrelationId(Session session, Destination response, BytesMessage requestMessage) throws JMSException {
String selector = String.format("JMSCorrelationID = '%s'", requestMessage.getJMSMessageID());
return session.createConsumer(response, selector);
}
private BytesMessage sendMessage(DataSource data, Session session, MessageProducer producer, Destination responseQueue) throws JMSException, UnsupportedEncodingException {
BytesMessage requestMessage = session.createBytesMessage();
requestMessage.setJMSReplyTo(responseQueue);
setAdditionalProperties(requestMessage);
requestMessage.writeBytes(data.getData().getBytes(config.getString("encoding")));
producer.send(requestMessage);
return requestMessage;
}
private void setAdditionalProperties(BytesMessage requestMessage) throws JMSException {
Map<String, String> properties = config.getSubConfig("additional_properties").getFlatStringMap();
for (String key : properties.keySet()) {
if (key.startsWith("SOAPJMS_")) {
requestMessage.setStringProperty(key, properties.get(key));
}
}
}
private Connection getConnection(InitialContext context) throws NamingException, JMSException {
ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup(config.getString("connection_factory_name"));
return connectionFactory.createConnection(config.getString("jms_username"), config.getString("jms_password"));
}
private Properties getProperties() {
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, config.getString("context_factory"));
env.put(Context.PROVIDER_URL, config.getString("provider_url"));
env.put(Context.SECURITY_PRINCIPAL, config.getString("jndi_username"));
env.put(Context.SECURITY_CREDENTIALS, config.getString("jndi_password"));
return env;
}
}