/**************************************************************************************
https://camel-extra.github.io
This program 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 3
of the License, or (at your option) any later version.
This program 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 program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
http://www.gnu.org/licenses/lgpl-3.0-standalone.html
***************************************************************************************/
package org.apacheextras.camel.component.zeromq;
import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;
public class ZeromqProducer extends DefaultProducer {
private static final Logger LOGGER = LoggerFactory.getLogger(ZeromqProducer.class);
private final ZeromqEndpoint endpoint;
private Socket socket;
private Context context;
private final MessageConverter messageConvertor;
private final SocketFactory socketFactory;
private final ContextFactory contextFactory;
private int shutdownWait = 5000;
private String[] topics;
public ZeromqProducer(ZeromqEndpoint endpoint, SocketFactory socketFactory, ContextFactory contextFactory) throws InstantiationException, IllegalAccessException {
super(endpoint);
this.endpoint = endpoint;
this.socketFactory = socketFactory;
this.contextFactory = contextFactory;
this.messageConvertor = (MessageConverter)endpoint.getMessageConvertor().newInstance();
}
public ContextFactory getContextFactory() {
return contextFactory;
}
public SocketFactory getSocketFactory() {
return socketFactory;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public void process(Exchange arg0) throws Exception {
byte[] body = messageConvertor.convert(arg0);
if (topics == null) {
socket.send(body, 0);
} else {
for (String topic : topics) {
byte[] t = topic.getBytes();
byte[] prefixed = new byte[t.length + body.length];
System.arraycopy(t, 0, prefixed, 0, t.length);
System.arraycopy(body, 0, prefixed, t.length, body.length);
socket.send(prefixed, 0);
}
}
arg0.getIn().setHeader(ZeromqConstants.HEADER_TIMESTAMP, System.currentTimeMillis());
arg0.getIn().setHeader(ZeromqConstants.HEADER_SOURCE, endpoint.getSocketAddress());
arg0.getIn().setHeader(ZeromqConstants.HEADER_SOCKET_TYPE, endpoint.getSocketType());
}
public void setShutdownWait(int shutdownWait) {
this.shutdownWait = shutdownWait;
}
@Override
public void start() throws Exception {
this.context = contextFactory.createContext(1);
this.socket = socketFactory.createProducerSocket(context, endpoint.getSocketType());
this.topics = endpoint.getTopics() == null ? null : endpoint.getTopics().split(",");
String addr = endpoint.getSocketAddress();
if (endpoint.getMode() == null || endpoint.getMode().equals("BIND")) {
LOGGER.info("Binding client to [{}]", addr);
socket.bind(addr);
LOGGER.info("Bound OK");
} else {
LOGGER.info("Connecting client to [{}]", addr);
socket.connect(addr);
LOGGER.info("Connected OK");
}
}
@Override
public void stop() throws Exception {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
socket.close();
} catch (Exception e) {
LOGGER.error("Could not close socket during stop() [{}]", e);
}
}
});
t.start();
LOGGER.debug("Waiting {}ms for producer socket to close", shutdownWait);
t.join(shutdownWait);
try {
context.term();
} catch (Exception e) {
LOGGER.error("Could not terminate the context during stop() [{}]", e);
}
}
}