/* * TeleStax, Open Source Cloud Communications * Copyright 2012, Telestax Inc and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This 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 2.1 of * the License, or (at your option) any later version. * * This software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.mobicents.smsc.domain; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.util.Map; import javolution.text.TextBuilder; import javolution.xml.XMLBinding; import javolution.xml.XMLObjectReader; import javolution.xml.XMLObjectWriter; import javolution.xml.stream.XMLStreamException; import org.apache.log4j.Logger; /** * * @author sergey vetyutnev * */ public class HomeRoutingManagement implements HomeRoutingManagementMBean { private static final Logger logger = Logger.getLogger(HomeRoutingManagement.class); 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 CC_MCCMNC_PERSIST_FILE_NAME = "cc_mccmnc.xml"; private static final String CORR_ID_FILE_NAME = "corrid.xml"; private static final String CC_MCCMNS_COLLECTION = "CcMccmncCollection"; private static final String CC_CORR_ID = "CorrId"; private static final long MAX_CORRELATION_ID = 10000000000L; private static final long CORR_ID_LAG = 1000; private static HomeRoutingManagement instance; private final String name; private String persistDir = null; private final TextBuilder persistFile = TextBuilder.newInstance(); private final TextBuilder persistFileCorrId = TextBuilder.newInstance(); private CcMccmncCollection ccMccmncCollection; private long correlationId = 0; private long loadedCorrelationId = -1; // private int ccMccmnsTableVersionActual = 1; // private int ccMccmnsTableVersionLoaded = 0; private HomeRoutingManagement(String name) { this.name = name; binding.setClassAttribute(CLASS_ATTRIBUTE); } public static HomeRoutingManagement getInstance(String name) { if (instance == null) { instance = new HomeRoutingManagement(name); } return instance; } public static HomeRoutingManagement getInstance() { return instance; } public String getName() { return name; } public String getPersistDir() { return persistDir; } public void setPersistDir(String persistDir) { this.persistDir = persistDir; } @Override public synchronized NextCorrelationIdResult getNextCorrelationId(String msisdn) { long corrId = doGetNextCorrelationId(); CcMccmnc ccMccmncValue = getCcMccmncValue(msisdn); String mccmnc; if (ccMccmncValue == null) { logger.warn("Found no entry in CcMccmncCollection for msisdn: " + msisdn); mccmnc = ""; } else { mccmnc = ccMccmncValue.getMccMnc(); } String corrIdS = String.valueOf(corrId); StringBuilder sb = new StringBuilder(); int len = mccmnc.length() + corrIdS.length(); if (len <= 15) { sb.append(mccmnc); for (int i1 = len; i1 < 15; i1++) { sb.append("0"); } sb.append(corrIdS); } else { sb.append(mccmnc); sb.append(corrIdS.substring(corrIdS.length() - (15 - mccmnc.length()))); } NextCorrelationIdResult res = new NextCorrelationIdResult(); res.setCorrelationId(sb.toString()); if (ccMccmncValue != null) res.setSmscAddress(ccMccmncValue.getSmsc()); return res; } @Override public void updateCcMccmncTable() { // ccMccmnsTableVersionActual++; this.load(); } protected synchronized long doGetNextCorrelationId() { correlationId++; if (correlationId >= MAX_CORRELATION_ID) correlationId = 1; // TODO: properly implement it with provided MSISDN -> IMSI recoding // table if (correlationId - loadedCorrelationId >= CORR_ID_LAG || correlationId < loadedCorrelationId || loadedCorrelationId < 0) { this.storeCorrId(); } return correlationId; } protected CcMccmnc getCcMccmncValue(String countryCode) { checkCcMccmncTable(); return ccMccmncCollection.findMccmnc(countryCode); } protected void checkCcMccmncTable() { // if (ccMccmncCollection != null && ccMccmnsTableVersionLoaded == ccMccmnsTableVersionActual) // return; // load(); } @Override public void addCcMccmnc(String countryCode, String mccMnc, String smsc) throws Exception { CcMccmncImpl ccMccmnc = new CcMccmncImpl(countryCode, mccMnc, smsc); ccMccmncCollection.addCcMccmnc(ccMccmnc); this.store(); } @Override public void modifyCcMccmnc(String countryCode, String mccMnc, String smsc) throws Exception { ccMccmncCollection.modifyCcMccmnc(countryCode, mccMnc, smsc); this.store(); } @Override public void removeCcMccmnc(String countryCode) throws Exception { ccMccmncCollection.removeCcMccmnc(countryCode); this.store(); } @Override public CcMccmnc getCcMccmnc(String countryCode) { return ccMccmncCollection.getCcMccmnc(countryCode); } @Override public Map<String, CcMccmncImpl> getCcMccmncMap() { return ccMccmncCollection.getCcMccmncMap(); } public void start() throws Exception { this.persistFile.clear(); if (persistDir != null) { this.persistFile.append(persistDir).append(File.separator).append(this.name).append("_").append(CC_MCCMNC_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(CC_MCCMNC_PERSIST_FILE_NAME); } this.persistFileCorrId.clear(); if (persistDir != null) { this.persistFileCorrId.append(persistDir).append(File.separator).append(this.name).append("_").append(CORR_ID_FILE_NAME); } else { persistFileCorrId.append(System.getProperty(SmscManagement.SMSC_PERSIST_DIR_KEY, System.getProperty(SmscManagement.USER_DIR_KEY))).append(File.separator) .append(this.name).append("_").append(CORR_ID_FILE_NAME); } logger.info(String.format("Loading home routing properties from %s", persistFile.toString())); this.load(); logger.info(String.format("Loading home routing corrId from %s", persistFileCorrId.toString())); this.loadCorrId(); } public void stop() throws Exception { // this.store(); if (loadedCorrelationId != -1 && correlationId != loadedCorrelationId) { this.storeCorrId(); } } /** * Persist */ public void store() { try { XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream(persistFile.toString())); writer.setBinding(binding); writer.setIndentation(TAB_INDENT); writer.write(ccMccmncCollection, CC_MCCMNS_COLLECTION, CcMccmncCollection.class); writer.close(); } catch (Exception e) { logger.error("Error while persisting the ccMccmncCollection in file", e); } } public void storeCorrId() { try { XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream(persistFileCorrId.toString())); writer.setBinding(binding); writer.setIndentation(TAB_INDENT); writer.write(correlationId, CC_CORR_ID, Long.class); writer.close(); } catch (Exception e) { logger.error("Error while persisting the home routing corrId value in file", e); } loadedCorrelationId = correlationId; } public synchronized void load() { // if (ccMccmncCollection != null && ccMccmnsTableVersionLoaded == ccMccmnsTableVersionActual) // return; ccMccmncCollection = new CcMccmncCollection(); XMLObjectReader reader = null; try { reader = XMLObjectReader.newInstance(new FileInputStream(persistFile.toString())); try { reader.setBinding(binding); ccMccmncCollection = reader.read(CC_MCCMNS_COLLECTION, CcMccmncCollection.class); logger.info("Successfully loaded CcMccmnsCollection: " + persistFile); } finally { reader.close(); } } catch (FileNotFoundException ex) { logger.warn("CcMccmnsCollection: file not found: " + persistFile.toString()); try { this.store(); } catch (Exception e) { } } catch (XMLStreamException ex) { logger.error("Error while loading CcMccmnsCollection from file" + persistFile.toString(), ex); } // ccMccmnsTableVersionLoaded = ccMccmnsTableVersionActual; } public synchronized void loadCorrId() { XMLObjectReader reader = null; try { reader = XMLObjectReader.newInstance(new FileInputStream(persistFileCorrId.toString())); try { reader.setBinding(binding); correlationId = reader.read(CC_CORR_ID, Long.class); correlationId += CORR_ID_LAG; loadedCorrelationId = -1; logger.info("Successfully loaded home routing corrId: " + persistFile); } finally { reader.close(); } } catch (FileNotFoundException ex) { logger.warn("home routing corrId value: file not found: " + persistFile.toString()); logger.warn("CcMccmnsCollection: file not found: " + persistFile.toString()); try { this.storeCorrId(); } catch (Exception e) { } } catch (XMLStreamException ex) { logger.error("Error while loading home routing corrId value from file" + persistFile.toString(), ex); } } }