/* * Copyright (c) 2007-2009, 2011, 2012, 2015, 2016 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.net4j.internal.jms; import org.eclipse.net4j.internal.jms.bundle.OM; import org.eclipse.net4j.internal.jms.messages.Messages; import org.eclipse.net4j.internal.jms.protocol.JMSAcknowledgeRequest; import org.eclipse.net4j.internal.jms.protocol.JMSClientMessageRequest; import org.eclipse.net4j.internal.jms.protocol.JMSCommitRequest; import org.eclipse.net4j.internal.jms.protocol.JMSRecoverRequest; import org.eclipse.net4j.internal.jms.protocol.JMSRegisterConsumerRequest; import org.eclipse.net4j.internal.jms.protocol.JMSRollbackRequest; import org.eclipse.net4j.internal.jms.util.DestinationUtil; import org.eclipse.net4j.internal.jms.util.MessageUtil; import org.eclipse.net4j.util.concurrent.QueueWorker; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; import org.eclipse.net4j.util.om.log.OMLogger; import javax.jms.BytesMessage; import javax.jms.Destination; import javax.jms.IllegalStateException; import javax.jms.JMSException; import javax.jms.MapMessage; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.ObjectMessage; import javax.jms.Queue; import javax.jms.QueueBrowser; import javax.jms.Session; import javax.jms.StreamMessage; import javax.jms.TemporaryQueue; import javax.jms.TemporaryTopic; import javax.jms.TextMessage; import javax.jms.Topic; import javax.jms.TopicSubscriber; import javax.transaction.TransactionRolledbackException; import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class SessionImpl extends QueueWorker<MessageConsumerImpl> implements Session { private ConnectionImpl connection; private int id; private boolean transacted; private int acknowledgeMode; private Map<Long, MessageConsumerImpl> consumers = new HashMap<Long, MessageConsumerImpl>(); /** * Outgoing transacted messages */ private List<MessageImpl> messages = new ArrayList<MessageImpl>(); private Set<MessageProducerImpl> producers = new HashSet<MessageProducerImpl>(); public SessionImpl(ConnectionImpl connection, int id, boolean transacted, int acknowledgeMode) throws JMSException { this.connection = connection; this.id = id; this.transacted = transacted; this.acknowledgeMode = acknowledgeMode; try { activate(); } catch (Exception ex) { throw new JMSException(ex.getMessage()); } } public ConnectionImpl getConnection() { return connection; } public int getID() { return id; } public boolean getTransacted() { return transacted; } public int getAcknowledgeMode() { return acknowledgeMode; } public MessageListener getMessageListener() { return null; } public void setMessageListener(MessageListener listener) { throw new UnsupportedOperationException(); } public MessageProducer createProducer(Destination destination) throws JMSException { DestinationImpl dest = DestinationUtil.convert(destination); MessageProducerImpl producer = new MessageProducerImpl(this, dest); producers.add(producer); return producer; } public MessageConsumer createConsumer(Destination destination) throws JMSException { return createConsumer(destination, null); } public MessageConsumer createConsumer(Destination destination, String messageSelector) throws JMSException { return createConsumer(destination, null, false); } public MessageConsumer createConsumer(Destination destination, String messageSelector, boolean noLocal) throws JMSException { DestinationImpl dest = DestinationUtil.convert(destination); long consumerID = registerConsumer(dest, messageSelector, noLocal, false); MessageConsumerImpl consumer = new MessageConsumerImpl(this, consumerID, dest, messageSelector); consumers.put(consumerID, consumer); return consumer; } public Queue createQueue(String queueName) { return new QueueImpl(queueName); } public TemporaryQueue createTemporaryQueue() { return new TemporaryQueueImpl(); } public QueueBrowser createBrowser(Queue queue) { return new QueueBrowserImpl(queue); } public QueueBrowser createBrowser(Queue queue, String messageSelector) { return new QueueBrowserImpl(queue, messageSelector); } public Topic createTopic(String topicName) { return new TopicImpl(topicName); } public TemporaryTopic createTemporaryTopic() { return new TemporaryTopicImpl(); } public TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException { return createDurableSubscriber(topic, name, null, false); } public TopicSubscriber createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal) throws JMSException { TopicImpl dest = (TopicImpl)DestinationUtil.convert(topic); long consumerID = registerConsumer(dest, messageSelector, noLocal, true); TopicSubscriberImpl subscriber = new TopicSubscriberImpl(this, consumerID, dest, name, messageSelector, noLocal); consumers.put(consumerID, subscriber); return subscriber; } public void unsubscribe(String name) { throw new NotYetImplementedException(); } public Message createMessage() { return new MessageImpl(); } public StreamMessage createStreamMessage() { return new StreamMessageImpl(); } public BytesMessage createBytesMessage() { return new BytesMessageImpl(); } public MapMessage createMapMessage() { return new MapMessageImpl(); } public ObjectMessage createObjectMessage() { return createObjectMessage(null); } public ObjectMessage createObjectMessage(Serializable object) { return new ObjectMessageImpl(object); } public TextMessage createTextMessage() { return createTextMessage(null); } public TextMessage createTextMessage(String text) { return new TextMessageImpl(text); } public void recover() throws JMSException { ensureNotTransacted(); try { stop(); new JMSRecoverRequest(connection.getProtocol(), id).send(); start(); } catch (Exception ex) { OM.LOG.error(ex); close(); } } public void commit() throws JMSException { ensureTransacted(); synchronized (messages) { try { String[] messageIDs = new JMSCommitRequest(connection.getProtocol(), id, messages).send(); if (messageIDs == null) { throw new TransactionRolledbackException(Messages.getString("SessionImpl_0")); //$NON-NLS-1$ } for (int i = 0; i < messageIDs.length; i++) { messages.get(i).setJMSMessageID(messageIDs[i]); } messages.clear(); } catch (JMSException ex) { throw ex; } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new JMSException(ex.getMessage()); } } } public void rollback() throws JMSException { ensureTransacted(); synchronized (messages) { try { if (!new JMSRollbackRequest(connection.getProtocol(), id).send()) { throw new JMSException(Messages.getString("SessionImpl_1")); //$NON-NLS-1$ } messages.clear(); } catch (JMSException ex) { throw ex; } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new JMSException(ex.getMessage()); } } } public void close() { LifecycleUtil.deactivate(this, OMLogger.Level.DEBUG); } public void run() { throw new UnsupportedOperationException(); } public long registerConsumer(DestinationImpl destination, String messageSelector, boolean noLocal, boolean durable) throws JMSException { try { return new JMSRegisterConsumerRequest(connection.getProtocol(), id, destination, messageSelector, noLocal, durable).send(); } catch (Exception ex) { throw new JMSException(ex.getMessage()); } } public void sendMessage(Message message) throws JMSException { if (getTransacted()) { synchronized (messages) { if (message instanceof MessageImpl) { messages.add(MessageUtil.copy(message)); } else { messages.add(MessageUtil.convert(message)); } } } else { try { MessageImpl impl = MessageUtil.convert(message); JMSClientMessageRequest request = new JMSClientMessageRequest(connection.getProtocol(), impl); String messageID = request.send(connection.getSendTimeout()); if (messageID == null) { throw new JMSException(Messages.getString("SessionImpl_2")); //$NON-NLS-1$ } message.setJMSMessageID(messageID); } catch (JMSException ex) { throw ex; } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { throw new JMSException(ex.getMessage()); } } } public boolean acknowledgeMessages(MessageConsumerImpl consumer) { try { new JMSAcknowledgeRequest(connection.getProtocol(), id).sendAsync(); return true; } catch (Exception ex) { OM.LOG.error(ex); return true; } } public void handleServerMessage(long consumerID, MessageImpl message) { message.setReceivingSession(this); MessageConsumerImpl consumer = consumers.get(consumerID); if (consumer == null) { OM.LOG.warn(MessageFormat.format(Messages.getString("SessionImpl_3"), consumerID)); //$NON-NLS-1$ return; } consumer.handleServerMessage(message); } @Override protected String getThreadName() { return "jms-session"; //$NON-NLS-1$ } /** * @since 2.0 */ @Override protected void work(WorkContext context, MessageConsumerImpl consumer) { consumer.dispatchMessage(); } private void ensureTransacted() throws IllegalStateException { if (!transacted) { throw new IllegalStateException("Session " + id + " not transacted"); //$NON-NLS-1$ //$NON-NLS-2$ } } private void ensureNotTransacted() throws IllegalStateException { if (transacted) { throw new IllegalStateException("Session " + id + " transacted"); //$NON-NLS-1$ //$NON-NLS-2$ } } private void start() { } private void stop() { } }