/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.openejb.resource.activemq.jms2; import org.apache.xbean.propertyeditor.PropertyEditorException; import org.apache.xbean.propertyeditor.PropertyEditors; import javax.jms.BytesMessage; import javax.jms.CompletionListener; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.JMSProducer; import javax.jms.JMSRuntimeException; import javax.jms.MapMessage; import javax.jms.Message; import javax.jms.MessageFormatRuntimeException; import javax.jms.MessageProducer; import javax.jms.ObjectMessage; import java.io.Serializable; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import static org.apache.openejb.resource.activemq.jms2.JMS2.toRuntimeException; import static org.apache.openejb.resource.activemq.jms2.JMS2.wrap; class JMSProducerImpl implements JMSProducer { private final JMSContextImpl context; private final MessageProducer producer; private final Map<String, Object> properties = new HashMap<>(); private volatile CompletionListener completionListener; private Destination jmsHeaderReplyTo; private String jmsHeaderCorrelationID; private byte[] jmsHeaderCorrelationIDAsBytes; private String jmsHeaderType; JMSProducerImpl(final JMSContextImpl jmsContext, final MessageProducer innerProducer) { this.context = jmsContext; this.producer = innerProducer; } private <T> T getProperty(final String key, final Class<T> type) { final Object val = properties.get(key); if (val == null || type.isInstance(val)) { return type.cast(val); } try { return type.cast(PropertyEditors.getValue(type, val.toString())); } catch (final PropertyEditorException pee) { throw new MessageFormatRuntimeException(pee.getMessage()); } } @Override public JMSProducer send(final Destination destination, final Message message) { if (message == null) { throw new MessageFormatRuntimeException("null message"); } try { if (jmsHeaderCorrelationID != null) { message.setJMSCorrelationID(jmsHeaderCorrelationID); } if (jmsHeaderCorrelationIDAsBytes != null && jmsHeaderCorrelationIDAsBytes.length > 0) { message.setJMSCorrelationIDAsBytes(jmsHeaderCorrelationIDAsBytes); } if (jmsHeaderReplyTo != null) { message.setJMSReplyTo(jmsHeaderReplyTo); } if (jmsHeaderType != null) { message.setJMSType(jmsHeaderType); } setProperties(message); if (completionListener != null) { producer.send(destination, message, completionListener); } else { producer.send(destination, message); } } catch (final JMSException e) { throw toRuntimeException(e); } return this; } private void setProperties(final Message message) throws JMSException { for (final Map.Entry<String, Object> entry : properties.entrySet()) { message.setObjectProperty(entry.getKey(), entry.getValue()); } } @Override public JMSProducer send(final Destination destination, final String body) { send(destination, wrap(context.createTextMessage(body))); return this; } @Override public JMSProducer send(final Destination destination, final Map<String, Object> body) { final MapMessage message = wrap(context.createMapMessage()); if (body != null) { try { for (final Map.Entry<String, Object> entry : body.entrySet()) { final String name = entry.getKey(); final Object v = entry.getValue(); if (v instanceof String) { message.setString(name, (String) v); } else if (v instanceof Long) { message.setLong(name, (Long) v); } else if (v instanceof Double) { message.setDouble(name, (Double) v); } else if (v instanceof Integer) { message.setInt(name, (Integer) v); } else if (v instanceof Character) { message.setChar(name, (Character) v); } else if (v instanceof Short) { message.setShort(name, (Short) v); } else if (v instanceof Boolean) { message.setBoolean(name, (Boolean) v); } else if (v instanceof Float) { message.setFloat(name, (Float) v); } else if (v instanceof Byte) { message.setByte(name, (Byte) v); } else if (v instanceof byte[]) { byte[] array = (byte[]) v; message.setBytes(name, array, 0, array.length); } else { message.setObject(name, v); } } } catch (final JMSException e) { throw new MessageFormatRuntimeException(e.getMessage()); } } send(destination, message); return this; } @Override public JMSProducer send(final Destination destination, final byte[] body) { final BytesMessage message = wrap(context.createBytesMessage()); if (body != null) { try { message.writeBytes(body); } catch (final JMSException e) { throw new MessageFormatRuntimeException(e.getMessage()); } } send(destination, message); return this; } @Override public JMSProducer send(final Destination destination, final Serializable body) { final ObjectMessage message = wrap(context.createObjectMessage(body)); send(destination, message); return this; } @Override public JMSProducer setDisableMessageID(final boolean value) { try { producer.setDisableMessageID(value); } catch (final JMSException e) { throw toRuntimeException(e); } return this; } @Override public boolean getDisableMessageID() { try { return producer.getDisableMessageID(); } catch (final JMSException e) { throw toRuntimeException(e); } } @Override public JMSProducer setDisableMessageTimestamp(final boolean value) { try { producer.setDisableMessageTimestamp(value); } catch (final JMSException e) { throw toRuntimeException(e); } return this; } @Override public boolean getDisableMessageTimestamp() { try { return producer.getDisableMessageTimestamp(); } catch (final JMSException e) { throw toRuntimeException(e); } } @Override public JMSProducer setDeliveryMode(final int deliveryMode) { try { producer.setDeliveryMode(deliveryMode); } catch (final JMSException e) { final JMSRuntimeException e2 = new JMSRuntimeException(e.getMessage()); e2.initCause(e); throw e2; } return this; } @Override public int getDeliveryMode() { try { return producer.getDeliveryMode(); } catch (final JMSException e) { final JMSRuntimeException e2 = new JMSRuntimeException(e.getMessage()); e2.initCause(e); throw e2; } } @Override public JMSProducer setPriority(final int priority) { try { producer.setPriority(priority); } catch (final JMSException e) { final JMSRuntimeException e2 = new JMSRuntimeException(e.getMessage()); e2.initCause(e); throw e2; } return this; } @Override public int getPriority() { try { return producer.getPriority(); } catch (final JMSException e) { final JMSRuntimeException e2 = new JMSRuntimeException(e.getMessage()); e2.initCause(e); throw e2; } } @Override public JMSProducer setTimeToLive(final long timeToLive) { try { producer.setTimeToLive(timeToLive); return this; } catch (final JMSException e) { final JMSRuntimeException e2 = new JMSRuntimeException(e.getMessage()); e2.initCause(e); throw e2; } } @Override public long getTimeToLive() { try { return producer.getTimeToLive(); } catch (final JMSException e) { final JMSRuntimeException e2 = new JMSRuntimeException(e.getMessage()); e2.initCause(e); throw e2; } } @Override public JMSProducer setDeliveryDelay(final long deliveryDelay) { try { producer.setDeliveryDelay(deliveryDelay); return this; } catch (final JMSException e) { JMSRuntimeException e2 = new JMSRuntimeException(e.getMessage()); e2.initCause(e); throw e2; } } @Override public long getDeliveryDelay() { try { return producer.getDeliveryDelay(); } catch (final Exception ignored) { // no-op } return 0; } @Override public JMSProducer setAsync(final CompletionListener completionListener) { this.completionListener = completionListener; return this; } @Override public CompletionListener getAsync() { return completionListener; } @Override public JMSProducer setProperty(final String name, final boolean value) { validName(name); properties.put(name, value); return this; } @Override public JMSProducer setProperty(final String name, final byte value) { validName(name); properties.put(name, value); return this; } @Override public JMSProducer setProperty(final String name, final short value) { validName(name); properties.put(name, value); return this; } @Override public JMSProducer setProperty(final String name, final int value) { validName(name); properties.put(name, value); return this; } @Override public JMSProducer setProperty(final String name, final long value) { validName(name); properties.put(name, value); return this; } @Override public JMSProducer setProperty(final String name, final float value) { validName(name); properties.put(name, value); return this; } @Override public JMSProducer setProperty(final String name, final double value) { validName(name); properties.put(name, value); return this; } @Override public JMSProducer setProperty(final String name, final String value) { validName(name); properties.put(name, value); return this; } @Override public JMSProducer clearProperties() { properties.clear(); return this; } @Override public boolean propertyExists(final String name) { return properties.containsKey(name); } @Override public JMSProducer setProperty(final String name, final Object value) { validName(name); if (value != null && !Boolean.class.isInstance(value) && !Byte.class.isInstance(value) && !Character.class.isInstance(value) && !Short.class.isInstance(value) && !Integer.class.isInstance(value) && !Long.class.isInstance(value) && !Float.class.isInstance(value) && !Double.class.isInstance(value) && !String.class.isInstance(value) && !byte[].class.isInstance(value)) { throw new MessageFormatRuntimeException("Unsupported type: " + value); } properties.put(name, value); return this; } @Override public boolean getBooleanProperty(final String name) { return getProperty(name, Boolean.class); } @Override public byte getByteProperty(final String name) { return getProperty(name, Byte.class); } @Override public short getShortProperty(final String name) { return getProperty(name, Short.class); } @Override public int getIntProperty(final String name) { return getProperty(name, Integer.class); } @Override public long getLongProperty(final String name) { return getProperty(name, Long.class); } @Override public float getFloatProperty(final String name) { return getProperty(name, Float.class); } @Override public double getDoubleProperty(final String name) { return getProperty(name, Double.class); } @Override public String getStringProperty(final String name) { return getProperty(name, String.class); } @Override public Object getObjectProperty(final String name) { return getProperty(name, Object.class); } @Override public Set<String> getPropertyNames() { return new HashSet<>(properties.keySet()); } @Override public JMSProducer setJMSCorrelationIDAsBytes(final byte[] correlationID) { if (correlationID == null || correlationID.length == 0) { throw new JMSRuntimeException("Please specify a non-zero length byte[]"); } jmsHeaderCorrelationIDAsBytes = Arrays.copyOf(correlationID, correlationID.length); return this; } @Override public byte[] getJMSCorrelationIDAsBytes() { return Arrays.copyOf(jmsHeaderCorrelationIDAsBytes, jmsHeaderCorrelationIDAsBytes.length); } @Override public JMSProducer setJMSCorrelationID(final String correlationID) { jmsHeaderCorrelationID = correlationID; return this; } @Override public String getJMSCorrelationID() { return jmsHeaderCorrelationID; } @Override public JMSProducer setJMSType(final String type) { jmsHeaderType = type; return this; } @Override public String getJMSType() { return jmsHeaderType; } @Override public JMSProducer setJMSReplyTo(final Destination replyTo) { jmsHeaderReplyTo = replyTo; return this; } @Override public Destination getJMSReplyTo() { return jmsHeaderReplyTo; } private void validName(final String name) { if (name == null || name.isEmpty()) { throw new IllegalArgumentException("name can't be blank"); } } }