/*
* Copyright 2006-2010 Daniel Henninger. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package net.sf.kraken;
import net.sf.kraken.roster.TransportBuddy;
import net.sf.kraken.session.cluster.TransportSessionRouter;
import net.sf.kraken.type.TransportType;
import org.apache.log4j.Logger;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener;
import org.xmpp.component.ComponentManager;
import java.util.Map;
/**
* Transport Instance
*
* Represents all information that needs to be tracked about a gateway instance.
*
* @author Daniel Henninger
*/
public class TransportInstance<B extends TransportBuddy> implements PropertyEventListener {
final static Logger Log = Logger.getLogger(TransportInstance.class);
private final ComponentManager componentManager;
private final String description;
private final String nameOfClass;
public BaseTransport<B> transport = null;
private final TransportType type;
private boolean enabled = false;
private boolean running = false;
private String subDomain;
private final TransportSessionRouter sessionRouter;
/**
* Creates a new transport instance.
*
* @param type Type of transport.
* @param description Short description of transport.
* @param classname Full name/path of class associated with instance.
* @param componentManager Component manager managing this instance.
* @param sessionRouter Session router managing this instance.
*/
public TransportInstance(TransportType type, String description, String classname, ComponentManager componentManager, TransportSessionRouter sessionRouter) {
this.description = description;
this.type = type;
this.nameOfClass = classname;
this.componentManager = componentManager;
this.sessionRouter = sessionRouter;
enabled = JiveGlobals.getBooleanProperty("plugin.gateway."+this.type.toString()+".enabled", false);
subDomain = JiveGlobals.getProperty("plugin.gateway."+this.type.toString()+".subdomain", this.type.toString());
}
/**
* Retrieves the name of the service (aka, subdomain)
*
* @return name of the service
*/
public String getName() {
return this.type.toString();
}
/**
* Returns whether this transport instance is enabled.
*
* @return true or false if instance is enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* Returns whether this transport instance is currently running.
*
* @return true or false if instance is currently running
*/
public boolean isRunning() {
return running;
}
/**
* Enables the transport instance and starts it if it's not already running.
*/
public void enable() {
enabled = true;
JiveGlobals.setProperty("plugin.gateway."+this.type.toString()+".enabled", "true");
if (!running) {
startInstance();
}
}
/**
* Disables the transport instance and stops it if it's running.
*/
public void disable() {
enabled = false;
JiveGlobals.setProperty("plugin.gateway."+this.type.toString()+".enabled", "false");
if (running) {
stopInstance();
}
}
/**
* Starts the transport instance if it's enabled and not already running.
*/
public void startInstance() {
if (!enabled || running) {
return;
}
Log.info("Starting transport service: "+type.toString());
transport = null;
//Log.debug("Loading class "+nameOfClass);
try {
transport = (BaseTransport)Class.forName(nameOfClass).newInstance();
transport.setup(this.type, this.description, sessionRouter);
}
catch (ClassNotFoundException e) {
Log.error("Unable to find class: "+nameOfClass);
return;
}
catch (InstantiationException e) {
Log.error("Unable to instantiate class: "+nameOfClass);
return;
}
catch (IllegalAccessException e) {
Log.error("Unable to access class: "+nameOfClass);
return;
}
// Automatically kill any current s2s connections with the JID we want to use.
SessionManager sessionManager = SessionManager.getInstance();
String fullJID = this.subDomain+"."+XMPPServer.getInstance().getServerInfo().getXMPPDomain();
boolean pause = false;
try {
for (Session sess : sessionManager.getIncomingServerSessions(fullJID)) {
sess.close();
pause = true;
}
}
catch (Exception ignored) {
// Session might have disappeared on its own
}
try {
Session sess = sessionManager.getOutgoingServerSession(fullJID);
if (sess != null) {
sess.close();
pause = true;
}
}
catch (Exception ignored) {
// Session might have disappeared on its own
}
try {
// Wait one second if we closed something.
if (pause) {
Thread.sleep(1000L);
}
}
catch (Exception ignored) {
// Hrm, interrupted? That's odd.
}
try {
componentManager.addComponent(this.subDomain, transport);
PropertyEventDispatcher.addListener(this);
running = true;
}
catch (Exception e) {
Log.error("Error while adding component "+this.subDomain+": ", e);
}
}
/**
* Stops the transport instance if it's running.
*/
public void stopInstance() {
if (!running) {
return;
}
Log.info("Stopping transport service: "+type.toString());
transport.shutdown();
PropertyEventDispatcher.removeListener(this);
try {
componentManager.removeComponent(this.subDomain);
}
catch (Exception e) {
Log.error("Error while removing component "+this.subDomain+": ", e);
}
transport = null;
running = false;
}
/**
* Retrieves actual transport associated with this instance.
*
* @return Transport that the instance is associated with.
*/
public BaseTransport<B> getTransport() {
return transport;
}
@SuppressWarnings("unchecked")
public void propertySet(String property, Map params) {
if (property.startsWith("plugin.gateway.")) {
if (property.equals("plugin.gateway."+this.type.toString()+".enabled")) {
enabled = Boolean.parseBoolean((String)params.get("value"));
if (enabled) {
if (!running) {
startInstance();
}
}
else {
if (running) {
stopInstance();
}
}
}
else if (property.equals("plugin.gateway."+this.type.toString()+".subdomain")) {
String newSubDomain = (String)params.get("value");
if (!newSubDomain.equals(this.subDomain)) {
if (running) {
stopInstance();
this.subDomain = newSubDomain;
startInstance();
}
}
}
}
}
@SuppressWarnings("unchecked")
public void propertyDeleted(String property, Map params) {
if (property.startsWith("plugin.gateway.")) {
if (property.equals("plugin.gateway."+this.type.toString()+".enabled")) {
if (running) {
stopInstance();
}
}
else if (property.equals("plugin.gateway."+this.type.toString()+".subdomain")) {
String newSubDomain = this.type.toString();
if (!newSubDomain.equals(this.subDomain)) {
if (running) {
stopInstance();
this.subDomain = newSubDomain;
startInstance();
}
}
}
}
}
@SuppressWarnings("unchecked")
public void xmlPropertySet(String property, Map params) {
propertySet(property, params);
}
@SuppressWarnings("unchecked")
public void xmlPropertyDeleted(String property, Map params) {
propertyDeleted(property, params);
}
}