/*
* MicroJIAC - A Lightweight Agent Framework
* This file is part of MicroJIAC STOMP-Client.
*
* Copyright (c) 2007-2012 DAI-Labor, Technische Universität Berlin
*
* This library includes software developed at DAI-Labor, Technische
* Universität Berlin (http://www.dai-labor.de)
*
* This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* $Id: StompCommunicationElement.java 23214 2009-05-06 12:18:42Z marcel $
*/
package de.jiac.micro.ext.stomp;
import java.io.IOException;
import java.util.Vector;
import org.slf4j.Logger;
import com.github.libxjava.lang.IClassLoader;
import de.jiac.micro.agent.IActuator;
import de.jiac.micro.agent.ISensor;
import de.jiac.micro.agent.handle.ICommunicationHandle;
import de.jiac.micro.agent.memory.IFact;
import de.jiac.micro.agent.memory.IShortTermMemory;
import de.jiac.micro.core.IHandle;
import de.jiac.micro.core.ILifecycleAware;
import de.jiac.micro.core.io.IAddress;
import de.jiac.micro.core.io.IMessage;
import de.jiac.micro.core.io.IMulticastAddress;
import de.jiac.micro.core.io.IUnicastAddress;
import de.jiac.micro.core.scope.AgentScope;
import de.jiac.micro.core.scope.Scope;
import de.jiac.micro.ext.stomp.Transport.ITransportDelegate;
import de.jiac.micro.internal.io.Message;
/**
* @author Vladimir
* @version $Revision: 23214 $
*
*/
public class StompCommunicationElement implements ISensor, IActuator, ICommunicationHandle, ILifecycleAware {
private final static class StompClient implements ITransportDelegate {
private final IClassLoader _classLoader;
private final IShortTermMemory _shortMemory;
protected StompTransport transport;
public StompClient(IClassLoader classLoader, IShortTermMemory stm) {
transport = new StompTransport();
transport.setTransportDelegate(this);
_shortMemory= stm;
_classLoader = classLoader;
}
public void onError(Transport source, Object error) {
if(error instanceof Throwable) {
AgentScope.getAgentReference().getLogger().error("onError", (Throwable) error);
} else {
AgentScope.getAgentReference().getLogger().error("onError:: " + String.valueOf(error));
}
}
public void onMessage(Transport source, IMessage message, String destName) {
_shortMemory.notice((IFact) message);
}
public IClassLoader getClassLoader() {
return _classLoader;
}
public Logger getLogger() {
return AgentScope.getAgentReference().getLogger("STOMP");
}
}
private Vector _groups;
private StompClient _client;
private StompAddress _localAddress;
private String _serverURI;
private IShortTermMemory _stm;
private boolean _started= false;
public IHandle getHandle() {
return this;
}
public IMessage createMessage() {
return new Message();
}
public void cleanup() {
_groups = null;
}
public void initialise() {
_groups = new Vector();
_client = new StompClient(Scope.getContainer().getClassLoader(), _stm);
_localAddress= new StompAddress(IAddress.UNICAST, "agent" + System.currentTimeMillis() + "h" + System.identityHashCode(AgentScope.getAgentReference()));
}
public void setServerURI(String serverURI) {
_serverURI= serverURI;
}
public void start() {
Logger logger= AgentScope.getAgentReference().getLogger("STOMP");
try {
// create Stomp connections to broker
if(_serverURI == null) {
logger.error("unspecified server URI");
}
_client.transport.setServerURL(_serverURI);
_client.transport.doStart();
} catch (IOException io) {
logger.error("cannot start the stomp protocol", io);
}
_started= true;
// register for our address
try {
_client.transport.doRegister(StompTransport.MBOX_PREFIX, _localAddress.getAddressName());
logger.debug("registered message box: '" + _localAddress.getAddressName() + "'");
} catch (IOException ie) {
logger.error("could not register for local address: '" + _localAddress + "'", ie);
}
// check groups and registrate now
for(int i= 0; i < _groups.size(); ++i) {
try {
_client.transport.doRegister(StompTransport.GROUP_PREFIX, (String) _groups.elementAt(i));
logger.debug("registered group: '" + (String) _groups.elementAt(i) + "'");
} catch (IOException e) {
logger.error("could not register for group: '" + _groups.elementAt(i) + "'", e);
}
}
}
public void stop() {
_started= false;
_client.transport.doStop();
}
public void setShortTermMemory(IShortTermMemory stm) {
_stm = stm;
}
public IUnicastAddress[] getLocalAddresses() {
return new IUnicastAddress[] {_localAddress};
}
public IMulticastAddress getMulticastAddressForName(String groupName) {
return new StompAddress(IAddress.MULTICAST, groupName);
}
public IAddress getAddressForString(String addressStr) {
return StompAddress.getAddressForString(addressStr);
}
public void joinGroup(IMulticastAddress address) throws IOException {
String group = ((StompAddress) address).getAddressName();
if(!_groups.contains(group)) {
_groups.addElement(group);
if(_started) {
_client.transport.doRegister(StompTransport.GROUP_PREFIX, group);
}
}
}
public void leaveGroup(IMulticastAddress address) throws IOException {
String group = ((StompAddress) address).getAddressName();
if(_groups.removeElement(group)) {
if(!_groups.contains(group)) {
_groups.addElement(group);
if(_started) {
_client.transport.doUnregister(StompTransport.GROUP_PREFIX, group);
}
}
}
}
public void sendMessage(IAddress address, IMessage message) throws IOException {
String addressName= ((StompAddress) address).getAddressName();
message.setHeader(IMessage.DefaultHeader.SOURCE_ADDRESS, _localAddress.toString());
message.setHeader(IMessage.DefaultHeader.TARGET_ADDRESS, address.toString());
switch(address.getType()) {
case IAddress.UNICAST: {
message.setHeader(StompTransport.PREFIX_HEADER, StompTransport.MBOX_PREFIX);
message.setHeader(StompTransport.DESTINATION_HEADER, addressName);
_client.transport.doSend(message);
break;
}
case IAddress.MULTICAST: {
message.setHeader(StompTransport.PREFIX_HEADER, StompTransport.GROUP_PREFIX);
message.setHeader(StompTransport.DESTINATION_HEADER, addressName);
_client.transport.doSend(message);
break;
}
default: {
throw new IOException("invalid address type " + address.getType());
}
}
}
}