All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zeromq.jms.protocol.event.ZmqSerializeEventHandler Maven / Gradle / Ivy

package org.zeromq.jms.protocol.event;

/*
 * Copyright (c) 2015 Jeremy Miller
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.zeromq.ZFrame;
import org.zeromq.ZMsg;
import org.zeromq.jms.ZmqException;
import org.zeromq.jms.ZmqMessage;
import org.zeromq.jms.annotation.ZmqComponent;
import org.zeromq.jms.annotation.ZmqUriParameter;
import org.zeromq.jms.protocol.ZmqAckEvent;
import org.zeromq.jms.protocol.ZmqEvent;
import org.zeromq.jms.protocol.ZmqHeartbeatEvent;
import org.zeromq.jms.protocol.ZmqSendEvent;
import org.zeromq.jms.protocol.ZmqSocketType;
import org.zeromq.jms.protocol.filter.ZmqFilterPolicy;

/**
 * Java object serialisation of messages. This would assume both ends have access to the ZeroMQ JMS wrapper.
 */
@ZmqComponent("serialize")
@ZmqUriParameter("event")
public class ZmqSerializeEventHandler implements ZmqEventHandler {
    private static final Logger LOGGER = Logger.getLogger(ZmqSerializeEventHandler.class.getCanonicalName());

    /**
     *  Implementation of the SEND event, the only interface supported by JMS serialisation.
     */
    private class SerializeEvent implements ZmqSendEvent {

        private final Object messageId;
        private final ZmqMessage message;

        /**
         * Construct the JMS based event.
         * @param message  the message
         */
        SerializeEvent(final ZmqMessage message) {
            this.messageId = null;
            this.message = message;
        }

        @Override
        public Object getMessageId() {
            return messageId;
        }

        @Override
        public ZmqMessage getMessage() {
            return message;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((messageId == null) ? 0 : messageId.hashCode());
            return result;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }

            if (obj == null) {
                return false;
            }

            if (getClass() != obj.getClass()) {
                return false;
            }

            SerializeEvent other = (SerializeEvent) obj;

            if (messageId == null) {
                if (other.messageId != null) {
                    return false;
                }
            } else if (!messageId.equals(other.messageId)) {
                return false;
            }

            return true;
        }

        @Override
        public String toString() {
            return "SerialozeEvent [messageId=" + messageId + ", message=" + message + "]";
        }
    }

    @Override
    public ZmqSendEvent createSendEvent(final ZmqMessage message) {
        return createSendEvent(null, message);
    }

    @Override
    public ZmqSendEvent createSendEvent(final Object messageId, final ZmqMessage message) {
        ZmqSendEvent event = new SerializeEvent(message);

        return event;
    }

    @Override
    public ZmqAckEvent createAckEvent(final ZmqEvent event) {
        throw new UnsupportedOperationException("This is not a supported operation.");
    }

    @Override
    public ZmqHeartbeatEvent createHeartbeatEvent() {
        throw new UnsupportedOperationException("This is not a supported operation.");
    }

    @Override
    public ZMsg createMsg(final ZmqSocketType socketType, final ZmqFilterPolicy filter, final ZmqEvent event) throws ZmqException {

        if (event instanceof ZmqSendEvent) {
            final ZmqSendEvent sendEvent = (ZmqSendEvent) event;
            final ZmqMessage message = sendEvent.getMessage();
            final String messageFilter = (filter == null) ? null : filter.resolve(message);
            final byte[] key = (messageFilter == null) ? null : messageFilter.getBytes();

            final ZMsg msg = new ZMsg();

            if (key != null) {
                msg.add(key);
            }

            final ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();

            try {
                final ObjectOutput objectOutput = new ObjectOutputStream(byteArrayOutput);

                objectOutput.writeObject(message);
                objectOutput.flush();
            } catch (IOException ex) {
                throw new ZmqException("Unable to convert message to and array of bytes: " + message, ex);
            }

            final byte[] data = byteArrayOutput.toByteArray();

            msg.add(data);

            return msg;
        }

        throw new UnsupportedOperationException("This is not a supported operation.");
    }

    @Override
    public ZmqEvent createEvent(final ZmqSocketType socketType, final ZMsg msg) throws ZmqException {
        if (msg.contentSize() == 0) {
            return null;
        }

        LinkedList msgFrames = new LinkedList();
        ZFrame msgFrame = msg.pop();

        // Get all address hops and actual data message
        while (msgFrame != null) {
            if (msgFrame.hasData()) {
                msgFrames.add(msgFrame);
            }
            msgFrame = msg.pop();
        }

        // The last is always the data messages, others are optional address hops
        // see:  http://zguide.zeromq.org/php:chapter3
        if (msgFrames.size() > 0) {
            final byte[] msgFrameData = msgFrames.getLast().getData();
            final ByteArrayInputStream byteArrayInput = new ByteArrayInputStream(msgFrameData);
            try {
                final ObjectInput objectInput = new ObjectInputStream(byteArrayInput);
                final ZmqMessage message = (ZmqMessage) objectInput.readObject();
                ZmqEvent sendEvent = new SerializeEvent(message);

                return sendEvent;
            } catch (IOException | ClassNotFoundException ex) {
                LOGGER.log(Level.SEVERE, "Unable to create event from ZMQ message?", ex);
                throw new ZmqException("Unable to create event from ZMQ message?", ex);
            }
        }

        throw new ZmqException("Unable to creae event fomr the ZMQ message");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy