/*****************************************************************************
* Copyright [2013] [Jules White] *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
****************************************************************************/
package org.magnum.soda.transport;
import java.net.URLEncoder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.engio.mbassy.listener.Listener;
import net.engio.mbassy.listener.Mode;
import org.magnum.soda.MsgBus;
import org.magnum.soda.msg.LocalAddress;
import org.magnum.soda.msg.Msg;
import org.magnum.soda.msg.Protocol;
import org.magnum.soda.proxy.ObjRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.eventbus.Subscribe;
public abstract class Transport {
private static final int DEFAULT_THREADS = 3;
private static final Logger Log = LoggerFactory.getLogger(Transport.class);
private TransportListener listener_;
private Protocol protocol_;
private MsgBus msgBus_;
private LocalAddress myAddress_;
private ExecutorService executor_ = Executors
.newFixedThreadPool(DEFAULT_THREADS);
public Transport(Protocol protocol, MsgBus msgBus, LocalAddress addr) {
super();
msgBus_ = msgBus;
myAddress_ = addr;
protocol_ = protocol;
msgBus_.subscribe(this);
init(myAddress_);
}
protected void init(LocalAddress addr) {
}
/**
* This method receives msgs that are posted to the msgbus by local objects.
* The method marshalls the msgs into a MsgContainer and asks the transport
* implementation to send them.
*
* @param m
*/
@Subscribe
@Listener(delivery = Mode.Concurrent)
public void handleLocalOutboundMsg(final Msg m) {
try {
if (!m.isMarked()) {
m.setSource(myAddress_.toString());
final MsgContainer cont = protocol_.outbound(m);
cont.setDestination(m.getDestination());
Runnable r = new Runnable() {
@Override
public void run() {
send(cont);
}
};
executor_.submit(r);
}
} catch (Exception e) {
Log.error("Unexpected transport error", e);
}
}
/**
* This method should be called by Transport subclasses to unmarshall recvd
* msgs and place them on the local msgbus.
*
* @param msgc
*/
public void receive(MsgContainer msgc) {
try {
String json = msgc.getMsg();
Msg msg = protocol_.inbound(json);
msg.mark();
msgBus_.publish(msg);
} catch (Exception e) {
Log.error("Unexpected transport error", e);
}
}
public LocalAddress getMyAddress() {
return myAddress_;
}
public TransportListener getListener() {
return listener_;
}
public void setListener(TransportListener listener) {
listener_ = listener;
}
public ExecutorService getExecutor() {
return executor_;
}
public void setExecutor(ExecutorService executor) {
executor_ = executor;
}
public Protocol getProtocol() {
return protocol_;
}
public void setProtocol(Protocol protocol) {
protocol_ = protocol;
}
public abstract boolean isConnected();
public abstract void connect(Address addr);
public abstract void disconnect();
/**
* This method should be overriden by Transport subclasses to send an
* outbound msg.
*
* @param msg
*/
public abstract void send(MsgContainer msg);
}