/*
* 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.transport.hybrid.stomp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
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.Connection;
import org.jboss.narayana.blacktie.jatmibroker.xatmi.ConnectionException;
public class StompReceiverImpl implements Receiver {
private static final Logger log = LogManager.getLogger(StompReceiverImpl.class);
private int timeout = 0;
private boolean closed;
private String destinationName;
private Socket socket;
private OutputStream outputStream;
private InputStream inputStream;
private org.jboss.narayana.blacktie.jatmibroker.core.transport.hybrid.stomp.Message pendingMessage;
private boolean ignoreSingleReceipt;
public StompReceiverImpl(String serviceName, boolean conversational, String type, Properties properties)
throws ConnectionException, IOException {
String qtype = "/queue/";
if (type != null) {
qtype = "/" + type + "/";
}
if (conversational) {
this.destinationName = qtype + "BTC_" + serviceName;
} else {
this.destinationName = qtype + "BTR_" + serviceName;
}
String host = (String) properties.get("StompConnectHost");
int port = Integer.parseInt((String) properties.get("StompConnectPort"));
String username = (String) properties.get("StompConnectUsr");
String password = (String) properties.get("StompConnectPwd");
this.socket = StompManagement.connect(host, port, username, password);
this.outputStream = socket.getOutputStream();
this.inputStream = socket.getInputStream();
org.jboss.narayana.blacktie.jatmibroker.core.transport.hybrid.stomp.Message message = new org.jboss.narayana.blacktie.jatmibroker.core.transport.hybrid.stomp.Message();
message.setCommand("SUBSCRIBE");
Map<String, String> headers = new HashMap<String, String>();
headers.put("destination", destinationName);
headers.put("receipt", destinationName);
headers.put("ack", "client");
message.setHeaders(headers);
StompManagement.send(message, outputStream);
org.jboss.narayana.blacktie.jatmibroker.core.transport.hybrid.stomp.Message receive = StompManagement.receive(socket,
inputStream);
if (receive.getCommand().equals("ERROR")) {
log.error(new String(receive.getBody()));
throw new ConnectionException(Connection.TPENOENT, new String(receive.getBody()));
} else if (receive.getCommand().equals("MESSAGE")) {
// TODO remove when moving to HQStomp
log.trace("Received a message rather than a receipt");
this.pendingMessage = receive;
ignoreSingleReceipt = true;
}
log.debug("Created a consumer on: " + destinationName + " with timeout: " + timeout);
}
public Object getReplyTo() throws ConnectionException {
return null;
}
public Message receive(long flagsIn) throws ConnectionException {
log.debug("Receiving from: " + destinationName);
org.jboss.narayana.blacktie.jatmibroker.core.transport.hybrid.stomp.Message receive = pendingMessage;
pendingMessage = null;
try {
if (receive == null) {
receive = StompManagement.receive(socket, inputStream);
// TODO remove when moving to HQStomp
if (receive != null && receive.getCommand().equals("RECEIPT") && ignoreSingleReceipt) {
ignoreSingleReceipt = false;
receive = StompManagement.receive(socket, inputStream);
}
log.debug("Received from: " + destinationName);
}
if (receive == null) {
log.debug("No message to return: " + destinationName);
return null;
}
if (!receive.getCommand().equals("MESSAGE")) {
throw new ConnectionException(Connection.TPESYSTEM, "Internal error, received unexpected receipt");
}
Message convertFromBytesMessage = convertFromBytesMessage(receive);
convertFromBytesMessage.setOutputStream(outputStream);
convertFromBytesMessage.setMessageId(receive.getHeaders().get("message-id"));
log.debug("Returning message from: " + destinationName);
return convertFromBytesMessage;
} catch (ConnectionException e) {
throw e;
} catch (Exception t) {
log.debug("Couldn't receive the message: " + t.getMessage(), t);
throw new ConnectionException(Connection.TPESYSTEM, "Couldn't receive the message", t);
}
}
public void close() throws ConnectionException {
log.debug("close");
if (closed) {
throw new ConnectionException(Connection.TPEPROTO, "Sender already closed");
}
try {
log.debug("closing socket: " + socket);
StompManagement.close(socket, outputStream, inputStream);
inputStream.close();
log.debug("closed input stream: " + inputStream);
socket.close();
log.debug("closed socket: " + socket);
closed = true;
} catch (Throwable t) {
log.debug("consumer could not be closed");
throw new ConnectionException(Connection.TPESYSTEM, "Could not delete the queue", t);
}
}
public org.jboss.narayana.blacktie.jatmibroker.core.transport.Message convertFromBytesMessage(
org.jboss.narayana.blacktie.jatmibroker.core.transport.hybrid.stomp.Message receive) {
log.trace("convertFromBytesMessage");
String controlIOR = receive.getHeaders().get("messagecontrol");
log.trace("got messagecontrol: " + controlIOR);
String replyTo = receive.getHeaders().get("messagereplyto");
log.trace("got messagereplyto: " + replyTo);
int len = Integer.parseInt(receive.getHeaders().get("content-length"));
log.trace("gotcontent-length: " + len);
String serviceName = receive.getHeaders().get("servicename");
log.trace("got servicename: " + serviceName);
int flags = new Integer(receive.getHeaders().get("messageflags"));
log.trace("got messageflags: " + flags);
int cd = new Integer(receive.getHeaders().get("messagecorrelationId"));
log.trace("got messagecorrelationId: " + cd);
String type = receive.getHeaders().get("messagetype");
log.trace("got messagetype: " + type);
String subtype = receive.getHeaders().get("messagesubtype");
log.trace("got messagesubtype: " + subtype);
log.debug("type: " + type + " subtype: " + subtype);
org.jboss.narayana.blacktie.jatmibroker.core.transport.Message toProcess = new org.jboss.narayana.blacktie.jatmibroker.core.transport.Message();
toProcess.type = type;
toProcess.subtype = subtype;
toProcess.replyTo = replyTo;
toProcess.serviceName = serviceName;
toProcess.flags = flags;
toProcess.cd = cd;
toProcess.len = len;
if (toProcess.type == "") {
toProcess.data = null;
} else {
toProcess.data = receive.getBody();
}
toProcess.control = controlIOR;
return toProcess;
}
public int determineTimeout(long flags) throws ConnectionException {
throw new ConnectionException(Connection.TPEPROTO, "Tried to retrieve the cd on mom receiver");
}
public int getCd() throws ConnectionException {
throw new ConnectionException(Connection.TPEPROTO, "Tried to retrieve the cd on mom receiver");
}
public Object getEndpoint() throws ConnectionException {
return socket;
}
}