/**
*
*/
package org.mobicents.smsc.domain;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.List;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.StandardMBean;
import javolution.text.TextBuilder;
import javolution.util.FastList;
import javolution.xml.XMLBinding;
import javolution.xml.XMLObjectReader;
import javolution.xml.XMLObjectWriter;
import javolution.xml.stream.XMLStreamException;
import org.apache.log4j.Logger;
import org.jboss.mx.util.MBeanServerLocator;
/**
* @author Amit Bhayani
*
*/
public class SipManagement implements SipManagementMBean {
private static final Logger logger = Logger.getLogger(SipManagement.class);
private static final String SIP_LIST = "sipList";
private static final String TAB_INDENT = "\t";
private static final String CLASS_ATTRIBUTE = "type";
private static final XMLBinding binding = new XMLBinding();
private static final String PERSIST_FILE_NAME = "sip.xml";
public static final String SIP_NAME = "SIP";
private final String name;
private String persistDir = null;
protected FastList<Sip> sips = new FastList<Sip>();
private final TextBuilder persistFile = TextBuilder.newInstance();
private MBeanServer mbeanServer = null;
private static SipManagement instance = null;
private final SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();
/**
*
*/
private SipManagement(String name) {
this.name = name;
binding.setClassAttribute(CLASS_ATTRIBUTE);
binding.setAlias(Sip.class, "sip");
}
protected static SipManagement getInstance(String name) {
if (instance == null) {
instance = new SipManagement(name);
}
return instance;
}
public static SipManagement getInstance() {
return instance;
}
public String getName() {
return name;
}
public String getPersistDir() {
return persistDir;
}
public void setPersistDir(String persistDir) {
this.persistDir = persistDir;
}
/*
* (non-Javadoc)
*
* @see org.mobicents.smsc.smpp.SipManagementMBean#getSips()
*/
@Override
public List<Sip> getSips() {
return sips.unmodifiable();
}
/*
* (non-Javadoc)
*
* @see
* org.mobicents.smsc.smpp.SipManagementMBean#getSipByName(java.lang.String)
*/
@Override
public Sip getSipByName(String sipName) {
for (FastList.Node<Sip> n = sips.head(), end = sips.tail(); (n = n.getNext()) != end;) {
Sip sip = n.getValue();
if (sip.getName().equals(sipName)) {
return sip;
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see
* org.mobicents.smsc.smpp.SipManagementMBean#getEsmeByClusterName(java.
* lang.String)
*/
@Override
public Sip getSipByClusterName(String sipClusterName) {
// TODO : For now there is only one SIP stack so below will work. But in
// future this logic should be changed when multiple SIP Stack support
// is added
for (FastList.Node<Sip> n = sips.head(), end = sips.tail(); (n = n.getNext()) != end;) {
Sip sip = n.getValue();
if (sip.getClusterName().equals(sipClusterName)) {
return sip;
}
}
return null;
}
public synchronized Sip createSip(String name, String clusterName, String host, int port, boolean chargingEnabled,
byte addressTon, byte addressNpi, String addressRange, boolean countersEnabled, int networkId) throws Exception {
for (FastList.Node<Sip> n = sips.head(), end = sips.tail(); (n = n.getNext()) != end;) {
Sip esme = n.getValue();
// Name should be unique
if (esme.getName().equals(name)) {
throw new Exception(String.format(SMSCOAMMessages.CREATE_SIP_FAIL_ALREADY_EXIST, name));
}
}// for loop
if (clusterName == null) {
clusterName = name;
}
Sip sip = new Sip(name, clusterName, host, port, chargingEnabled, addressTon, addressNpi, addressRange,
countersEnabled, networkId);
sip.sipManagement = this;
sips.add(sip);
this.store();
this.registerSipMbean(sip);
return sip;
}
public Sip destroySip(String esmeName) throws Exception {
Sip esme = this.getSipByName(esmeName);
if (esme == null) {
throw new Exception(String.format(SMSCOAMMessages.SIP_NOT_FOUND, esmeName));
}
// if (esme.isStarted()) {
// throw new
// Exception(String.format(SMSCOAMMessages.DELETE_ESME_FAILED_ESME_STARTED));
// }
sips.remove(esme);
this.store();
this.unregisterSipMbean(esme.getName());
return esme;
}
public void start() throws Exception {
try {
this.mbeanServer = MBeanServerLocator.locateJBoss();
} catch (Exception e) {
this.logger.error("Exception when obtaining of MBeanServer: " + e.getMessage(), e);
}
this.persistFile.clear();
if (persistDir != null) {
this.persistFile.append(persistDir).append(File.separator).append(this.name).append("_")
.append(PERSIST_FILE_NAME);
} else {
persistFile
.append(System.getProperty(SmscManagement.SMSC_PERSIST_DIR_KEY,
System.getProperty(SmscManagement.USER_DIR_KEY))).append(File.separator).append(this.name)
.append("_").append(PERSIST_FILE_NAME);
}
logger.info(String.format("Loading SIP configuration from %s", persistFile.toString()));
try {
this.load();
} catch (FileNotFoundException e) {
logger.warn(String.format("Failed to load the SS7 configuration file. \n%s", e.getMessage()));
}
for (FastList.Node<Sip> n = sips.head(), end = sips.tail(); (n = n.getNext()) != end;) {
Sip sip = n.getValue();
this.registerSipMbean(sip);
}
if (sips.size() == 0) {
// TODO : We hard coded creation of SIP here as there will always be
// only one SIP. However in future when we allow adding more SIP
// stack, this can be changed
this.createSip(SIP_NAME, SIP_NAME, "127.0.0.1", 5065, false,
(byte) smscPropertiesManagement.getDefaultTon(), (byte) smscPropertiesManagement.getDefaultNpi(),
null, false, 0);
}
}
public void stop() throws Exception {
this.store();
for (FastList.Node<Sip> n = sips.head(), end = sips.tail(); (n = n.getNext()) != end;) {
Sip esme = n.getValue();
// this.stopWrappedSession(esme);
this.unregisterSipMbean(esme.getName());
}
}
/**
* Load and create LinkSets and Link from persisted file
*
* @throws Exception
*/
public void load() throws FileNotFoundException {
XMLObjectReader reader = null;
try {
reader = XMLObjectReader.newInstance(new FileInputStream(persistFile.toString()));
reader.setBinding(binding);
this.sips = reader.read(SIP_LIST, FastList.class);
// Populate cluster
for (FastList.Node<Sip> n = this.sips.head(), end = this.sips.tail(); (n = n.getNext()) != end;) {
Sip sip = n.getValue();
sip.sipManagement = this;
String sipClusterName = sip.getClusterName();
}
reader.close();
} catch (XMLStreamException ex) {
// this.logger.info(
// "Error while re-creating Linksets from persisted file", ex);
}
}
/**
* Persist
*/
public void store() {
// TODO : Should we keep reference to Objects rather than recreating
// everytime?
try {
XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream(persistFile.toString()));
writer.setBinding(binding);
// Enables cross-references.
// writer.setReferenceResolver(new XMLReferenceResolver());
writer.setIndentation(TAB_INDENT);
writer.write(sips, SIP_LIST, FastList.class);
writer.close();
} catch (Exception e) {
logger.error("Error while persisting the Rule state in file", e);
}
}
private void registerSipMbean(Sip esme) {
try {
ObjectName esmeObjNname = new ObjectName(SmscManagement.JMX_DOMAIN + ":layer=Sip,name=" + esme.getName());
StandardMBean esmeMxBean = new StandardMBean(esme, SipMBean.class, true);
if (this.mbeanServer != null)
this.mbeanServer.registerMBean(esmeMxBean, esmeObjNname);
} catch (InstanceAlreadyExistsException e) {
logger.error(String.format("Error while registering MBean for SIP %s", esme.getName()), e);
} catch (MBeanRegistrationException e) {
logger.error(String.format("Error while registering MBean for SIP %s", esme.getName()), e);
} catch (NotCompliantMBeanException e) {
logger.error(String.format("Error while registering MBean for SIP %s", esme.getName()), e);
} catch (MalformedObjectNameException e) {
logger.error(String.format("Error while registering MBean for SIP %s", esme.getName()), e);
}
}
private void unregisterSipMbean(String esmeName) {
try {
ObjectName esmeObjNname = new ObjectName(SmscManagement.JMX_DOMAIN + ":layer=Sip,name=" + esmeName);
if (this.mbeanServer != null)
this.mbeanServer.unregisterMBean(esmeObjNname);
} catch (MBeanRegistrationException e) {
logger.error(String.format("Error while unregistering MBean for ESME %s", esmeName), e);
} catch (InstanceNotFoundException e) {
logger.error(String.format("Error while unregistering MBean for ESME %s", esmeName), e);
} catch (MalformedObjectNameException e) {
logger.error(String.format("Error while unregistering MBean for ESME %s", esmeName), e);
}
}
}