/* * JBoss, Home of Professional Open Source * Copyright 2008, Red Hat, Inc., and others contributors as indicated * by the @authors tag. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * 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, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.jboss.narayana.blacktie.jatmibroker.core.server; import java.io.IOException; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jboss.narayana.blacktie.jatmibroker.core.conf.ConfigurationException; import org.jboss.narayana.blacktie.jatmibroker.core.transport.Message; import org.jboss.narayana.blacktie.jatmibroker.core.transport.Receiver; import org.jboss.narayana.blacktie.jatmibroker.xatmi.BlackTieService; import org.jboss.narayana.blacktie.jatmibroker.xatmi.Connection; import org.jboss.narayana.blacktie.jatmibroker.xatmi.ConnectionException; import org.jboss.narayana.blacktie.jatmibroker.xatmi.Response; import org.jboss.narayana.blacktie.jatmibroker.xatmi.Service; import org.jboss.narayana.blacktie.jatmibroker.xatmi.TPSVCINFO; /** * This is the compatriot to the MDBBlacktieService found in the xatmi.mdb package. It is a wrapper for user services. */ public class ServiceDispatcher extends BlackTieService implements Runnable { private static final Logger log = LogManager.getLogger(ServiceDispatcher.class); private Service callback; private Receiver receiver; private Thread thread; private volatile boolean closing; private String serviceName; private Object closeLock = new Object(); private String threadName; private boolean closed; ServiceDispatcher(String serviceName, Service callback, Receiver receiver, int index) throws ConfigurationException { super(serviceName); this.serviceName = serviceName; this.callback = callback; this.receiver = receiver; this.threadName = serviceName + "-Dispatcher-" + index; thread = new Thread(this, threadName); thread.start(); log.debug("Created: " + thread.getName()); } public void run() { log.debug("Running"); while (!closing) { Message message = null; try { message = receiver.receive(0); log.trace("Received"); if (message != null && !closing) { // Process the consumed message try { this.processMessage(serviceName, message); log.trace("Processed"); } catch (Throwable t) { log.error("Can't process the message", t); } try { // Assumes the message was received from stomp - // fair // assumption outside of an MDB message.ack(); } catch (IOException t) { log.error("Can't ack the message", t); } } } catch (ConnectionException e) { if (closing) { log.trace("Got an exception during close: " + e.getMessage(), e); break; } if (e.getTperrno() == Connection.TPETIME) { log.debug("Got a timeout"); } else { log.error("Could not receive the message: " + e.getMessage(), e); break; } } catch (Throwable t) { log.warn("Got throwable trying to receive: " + t.getMessage(), t); } } synchronized (closeLock) { log.debug("Close the thread"); closed = true; closeLock.notify(); } } public void startClose() { log.trace("Attempting to close: " + threadName); closing = true; log.trace("Closed set: " + threadName); } public void close() throws ConnectionException { log.trace("closing: " + threadName); log.trace("Closing receiver"); receiver.close(); log.trace("Closing receiver"); synchronized (closeLock) { try { // Stop the receive thread.interrupt(); log.trace("Joining"); if (!closed) { closeLock.wait(); } log.trace("Joined"); } catch (InterruptedException e) { log.error("Could not join the dispatcher", e); } } log.trace("closed"); } public Response tpservice(TPSVCINFO svcinfo) throws ConnectionException, ConfigurationException { log.trace("Invoking callback"); return callback.tpservice(svcinfo); } }