All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mobicents.smsc.slee.services.mt.MtCommonSbb Maven / Gradle / Ivy

There is a newer version: 7.4.179
Show newest version
/*
 * TeleStax, Open Source Cloud Communications  Copyright 2012. 
 * 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.slee.services.mt;

import java.util.ArrayList;
import java.util.Date;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.slee.ActivityContextInterface;
import javax.slee.CreateException;
import javax.slee.RolledBackContext;
import javax.slee.Sbb;
import javax.slee.SbbContext;
import javax.slee.facilities.Tracer;
import javax.slee.resource.ResourceAdaptorTypeID;

import javolution.util.FastList;

import org.mobicents.protocols.ss7.indicator.NatureOfAddress;
import org.mobicents.protocols.ss7.indicator.NumberingPlan;
import org.mobicents.protocols.ss7.map.api.MAPParameterFactory;
import org.mobicents.protocols.ss7.map.api.MAPProvider;
import org.mobicents.protocols.ss7.map.api.MAPSmsTpduParameterFactory;
import org.mobicents.protocols.ss7.map.api.dialog.MAPUserAbortChoice;
import org.mobicents.protocols.ss7.map.api.dialog.ProcedureCancellationReason;
import org.mobicents.protocols.ss7.map.api.dialog.ResourceUnavailableReason;
import org.mobicents.protocols.ss7.map.api.errors.MAPErrorMessage;
import org.mobicents.protocols.ss7.map.api.primitives.AddressNature;
import org.mobicents.protocols.ss7.map.api.primitives.AddressString;
import org.mobicents.protocols.ss7.map.api.primitives.ISDNAddressString;
import org.mobicents.protocols.ss7.map.api.service.sms.SMDeliveryOutcome;
import org.mobicents.protocols.ss7.sccp.impl.parameter.ParameterFactoryImpl;
import org.mobicents.protocols.ss7.sccp.parameter.ParameterFactory;
import org.mobicents.protocols.ss7.sccp.parameter.SccpAddress;
import org.mobicents.protocols.ss7.tcap.asn.comp.Problem;
import org.mobicents.slee.SbbContextExt;
import org.mobicents.slee.resource.map.MAPContextInterfaceFactory;
import org.mobicents.slee.resource.map.events.DialogAccept;
import org.mobicents.slee.resource.map.events.DialogClose;
import org.mobicents.slee.resource.map.events.DialogDelimiter;
import org.mobicents.slee.resource.map.events.DialogNotice;
import org.mobicents.slee.resource.map.events.DialogProviderAbort;
import org.mobicents.slee.resource.map.events.DialogReject;
import org.mobicents.slee.resource.map.events.DialogRelease;
import org.mobicents.slee.resource.map.events.DialogRequest;
import org.mobicents.slee.resource.map.events.DialogTimeout;
import org.mobicents.slee.resource.map.events.DialogUserAbort;
import org.mobicents.slee.resource.map.events.ErrorComponent;
import org.mobicents.slee.resource.map.events.InvokeTimeout;
import org.mobicents.slee.resource.map.events.RejectComponent;
import org.mobicents.smsc.cassandra.DBOperations_C2;
import org.mobicents.smsc.cassandra.DatabaseType;
import org.mobicents.smsc.cassandra.PersistenceException;
import org.mobicents.smsc.domain.MProcManagement;
import org.mobicents.smsc.domain.SmscPropertiesManagement;
import org.mobicents.smsc.domain.SmscStatAggregator;
import org.mobicents.smsc.domain.StoreAndForwordMode;
import org.mobicents.smsc.library.CdrGenerator;
import org.mobicents.smsc.library.ErrorCode;
import org.mobicents.smsc.library.MessageDeliveryResultResponseInterface;
import org.mobicents.smsc.library.MessageUtil;
import org.mobicents.smsc.library.Sms;
import org.mobicents.smsc.library.SmsSet;
import org.mobicents.smsc.library.SmsSetCache;
import org.mobicents.smsc.library.TargetAddress;
import org.mobicents.smsc.mproc.impl.MProcResult;
import org.mobicents.smsc.slee.resources.persistence.PersistenceRAInterface;
import org.mobicents.smsc.slee.resources.persistence.SmsSubmitData;
import org.mobicents.smsc.slee.resources.scheduler.SchedulerActivity;
import org.mobicents.smsc.slee.resources.scheduler.SchedulerRaSbbInterface;

/**
 * 
 * @author amit bhayani
 * @author sergey vetyutnev
 * 
 */
public abstract class MtCommonSbb implements Sbb, ReportSMDeliveryStatusInterface2 {

	private static final ResourceAdaptorTypeID PERSISTENCE_ID = new ResourceAdaptorTypeID(
			"PersistenceResourceAdaptorType", "org.mobicents", "1.0");
	private static final ResourceAdaptorTypeID SCHEDULE_ID = new ResourceAdaptorTypeID("SchedulerResourceAdaptorType",
			"org.mobicents", "1.0");
	private static final String PERSISTENCE_LINK = "PersistenceResourceAdaptor";
	private static final String SCHEDULE_LINK = "SchedulerResourceAdaptor";

	protected static final String MAP_USER_ABORT_CHOICE_USER_SPECIFIC_REASON = "userSpecificReason";
	protected static final String MAP_USER_ABORT_CHOICE_USER_RESOURCE_LIMITATION = "userResourceLimitation";
	protected static final String MAP_USER_ABORT_CHOICE_UNKNOWN = "DialogUserAbort_Unknown";

	protected static final SmscPropertiesManagement smscPropertiesManagement = SmscPropertiesManagement.getInstance();

	private final String className;

	protected Tracer logger;
	protected SbbContextExt sbbContext;

	protected MAPContextInterfaceFactory mapAcif;
	protected MAPProvider mapProvider;
	protected MAPParameterFactory mapParameterFactory;
	protected MAPSmsTpduParameterFactory mapSmsTpduParameterFactory;
	protected ParameterFactory sccpParameterFact;

	private AddressString serviceCenterAddress;
	private SccpAddress serviceCenterSCCPAddress = null;

	protected PersistenceRAInterface persistence;
	protected SchedulerRaSbbInterface scheduler;
	protected SmscStatAggregator smscStatAggregator = SmscStatAggregator.getInstance();

	public MtCommonSbb(String className) {
		this.className = className;
	}

	public PersistenceRAInterface getStore() {
		return this.persistence;
	}

	public SchedulerRaSbbInterface getScheduler() {
		return this.scheduler;
	}

	/**
	 * MAP Components Events
	 */

	public void onErrorComponent(ErrorComponent event, ActivityContextInterface aci) {
        SmsSubmitData smsDeliveryData = this.doGetSmsSubmitData();
        String targetId = null;
        if (smsDeliveryData != null) {
            targetId = smsDeliveryData.getTargetId();
        }

        if (this.logger.isInfoEnabled()) {
            this.logger.info("\nRx :  onErrorComponent " + event + " targetId=" + targetId + ", Dialog=" + event.getMAPDialog());
        }
	}

	public void onRejectComponent(RejectComponent event, ActivityContextInterface aci) {
        SmsSubmitData smsDeliveryData = this.doGetSmsSubmitData();
        String targetId = null;
        if (smsDeliveryData != null) {
            targetId = smsDeliveryData.getTargetId();
        }

		this.logger.severe("\nRx :  onRejectComponent targetId=" + targetId + ", " + event);
	}

	protected String getRejectComponentReason(RejectComponent event) {
		Problem problem = event.getProblem();
		String reason = null;
		switch (problem.getType()) {
		case General:
			reason = problem.getGeneralProblemType().toString();
			break;
		case Invoke:
			reason = problem.getInvokeProblemType().toString();
			break;
		case ReturnResult:
			reason = problem.getReturnResultProblemType().toString();
			break;
		case ReturnError:
			reason = problem.getReturnErrorProblemType().toString();
			break;
		default:
			reason = "RejectComponent_unknown_" + problem.getType();
			break;
		}

		try {
			event.getMAPDialog().close(false);
		} catch (Exception e) {
		}

		return reason;
	}

	public void onInvokeTimeout(InvokeTimeout evt, ActivityContextInterface aci) {
        SmsSubmitData smsDeliveryData = this.doGetSmsSubmitData();
        String targetId = null;
        if (smsDeliveryData != null) {
            targetId = smsDeliveryData.getTargetId();
        }

		if (logger.isWarningEnabled()) {
			this.logger.warning("\nRx : onInvokeTimeout targetId=" + targetId + ", " + evt);
		}
	}

	/**
	 * Dialog Events
	 */

	public void onDialogReject(DialogReject evt, ActivityContextInterface aci) {
        SmsSubmitData smsDeliveryData = this.doGetSmsSubmitData();
        String targetId = null;
        if (smsDeliveryData != null) {
            targetId = smsDeliveryData.getTargetId();
        }

		if (logger.isWarningEnabled()) {
			this.logger.warning("\nRx : onDialogReject targetId=" + targetId + ", " + evt);
		}
	}

	public void onDialogProviderAbort(DialogProviderAbort evt, ActivityContextInterface aci) {
        SmsSubmitData smsDeliveryData = this.doGetSmsSubmitData();
        String targetId = null;
        if (smsDeliveryData != null) {
            targetId = smsDeliveryData.getTargetId();
        }

		if (logger.isWarningEnabled()) {
			this.logger.warning("\nRx :  onDialogProviderAbort targetId=" + targetId + ", " + evt);
		}
	}

	public void onDialogUserAbort(DialogUserAbort evt, ActivityContextInterface aci) {
        SmsSubmitData smsDeliveryData = this.doGetSmsSubmitData();
        String targetId = null;
        if (smsDeliveryData != null) {
            targetId = smsDeliveryData.getTargetId();
        }

		if (logger.isWarningEnabled()) {
			this.logger.warning("\nRx :  onDialogUserAbort targetId=" + targetId + ", " + evt);
		}
	}

	protected String getUserAbortReason(DialogUserAbort evt) {
		MAPUserAbortChoice userReason = evt.getUserReason();
		String reason = null;
		if (userReason.isUserSpecificReason()) {
			reason = MAP_USER_ABORT_CHOICE_USER_SPECIFIC_REASON;
		} else if (userReason.isUserResourceLimitation()) {
			reason = MAP_USER_ABORT_CHOICE_USER_RESOURCE_LIMITATION;
		} else if (userReason.isResourceUnavailableReason()) {
			ResourceUnavailableReason resourceUnavailableReason = userReason.getResourceUnavailableReason();
			reason = resourceUnavailableReason.toString();
		} else if (userReason.isProcedureCancellationReason()) {
			ProcedureCancellationReason procedureCancellationReason = userReason.getProcedureCancellationReason();
			reason = procedureCancellationReason.toString();
		} else {
			reason = MAP_USER_ABORT_CHOICE_UNKNOWN;
		}
		return reason;
	}

	public void onDialogTimeout(DialogTimeout evt, ActivityContextInterface aci) {
        SmsSubmitData smsDeliveryData = this.doGetSmsSubmitData();
        String targetId = null;
        if (smsDeliveryData != null) {
            targetId = smsDeliveryData.getTargetId();
        }

		if (logger.isWarningEnabled()) {
			this.logger.warning("\nRx :  onDialogTimeout targetId=" + targetId + ", " + evt);
		}
	}

	public void onDialogDelimiter(DialogDelimiter evt, ActivityContextInterface aci) {
		if (logger.isFineEnabled()) {
			this.logger.fine("\nRx :  onDialogDelimiter " + evt);
		}
	}

	public void onDialogAccept(DialogAccept evt, ActivityContextInterface aci) {
		if (logger.isFineEnabled()) {
			this.logger.fine("\nRx :  onDialogAccept=" + evt);
		}
	}

	public void onDialogClose(DialogClose evt, ActivityContextInterface aci) {
		if (logger.isFineEnabled()) {
			this.logger.fine("\nRx :  onDialogClose=" + evt);
		}
	}

	public void onDialogNotice(DialogNotice evt, ActivityContextInterface aci) {
        SmsSubmitData smsDeliveryData = this.doGetSmsSubmitData();
        String targetId = null;
        if (smsDeliveryData != null) {
            targetId = smsDeliveryData.getTargetId();
        }

		if (logger.isWarningEnabled()) {
			this.logger.warning("\nRx :  onDialogNotice targetId=" + targetId + ", " + evt);
		}
	}

	public void onDialogRequest(DialogRequest evt, ActivityContextInterface aci) {
		if (logger.isFineEnabled()) {
			this.logger.fine("\nRx :  onDialogRequest=" + evt);
		}
	}

	public void onDialogRelease(DialogRelease evt, ActivityContextInterface aci) {
		if (logger.isInfoEnabled()) {
			this.logger.info("\nRx :  DialogRelease=" + evt);
		}
	}

	/**
	 * Life cycle methods
	 */

	@Override
	public void sbbActivate() {
		// TODO Auto-generated method stub

	}

	@Override
	public void sbbCreate() throws CreateException {
		// TODO Auto-generated method stub

	}

	@Override
	public void sbbExceptionThrown(Exception arg0, Object arg1, ActivityContextInterface arg2) {
		// TODO Auto-generated method stub

	}

	@Override
	public void sbbLoad() {
		// TODO Auto-generated method stub

	}

	@Override
	public void sbbPassivate() {
		// TODO Auto-generated method stub

	}

	@Override
	public void sbbPostCreate() throws CreateException {
		// TODO Auto-generated method stub

	}

	@Override
	public void sbbRemove() {
		// TODO Auto-generated method stub

	}

	@Override
	public void sbbRolledBack(RolledBackContext arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void sbbStore() {
		// TODO Auto-generated method stub

	}

	@Override
	public void setSbbContext(SbbContext sbbContext) {
		this.sbbContext = (SbbContextExt) sbbContext;

		try {
			Context ctx = (Context) new InitialContext().lookup("java:comp/env");
			this.mapAcif = (MAPContextInterfaceFactory) ctx.lookup("slee/resources/map/2.0/acifactory");
			this.mapProvider = (MAPProvider) ctx.lookup("slee/resources/map/2.0/provider");
			this.mapParameterFactory = this.mapProvider.getMAPParameterFactory();
			this.mapSmsTpduParameterFactory = this.mapProvider.getMAPSmsTpduParameterFactory();
			this.sccpParameterFact = new ParameterFactoryImpl();

			this.logger = this.sbbContext.getTracer(this.className);

			this.persistence = (PersistenceRAInterface) this.sbbContext.getResourceAdaptorInterface(PERSISTENCE_ID,
					PERSISTENCE_LINK);
			this.scheduler = (SchedulerRaSbbInterface) this.sbbContext.getResourceAdaptorInterface(SCHEDULE_ID,
					SCHEDULE_LINK);

		} catch (Exception ne) {
			logger.severe("Could not set SBB context:", ne);
		}
		// TODO : Handle proper error
	}

	@Override
	public void unsetSbbContext() {

	}

	/**
	 * Sbb ACI
	 */
	// public abstract MtActivityContextInterface
	// asSbbActivityContextInterface(ActivityContextInterface aci);

	/**
	 * TODO : This is repetitive in each Sbb. Find way to make it static
	 * probably?
	 * 
	 * This is our own number. We are Service Center.
	 * 
	 * @return
	 */
	protected AddressString getServiceCenterAddressString(int networkId) {
        if (networkId == 0) {
            if (this.serviceCenterAddress == null) {
                this.serviceCenterAddress = this.mapParameterFactory.createAddressString(AddressNature.international_number,
                        org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan.ISDN, smscPropertiesManagement.getServiceCenterGt());
            }
            return this.serviceCenterAddress;
        } else {
            return this.mapParameterFactory.createAddressString(AddressNature.international_number,
                    org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan.ISDN, smscPropertiesManagement.getServiceCenterGt(networkId));
        }
	}

	/**
	 * TODO: This should be configurable and static as well
	 * 
	 * This is our (Service Center) SCCP Address for GT
	 * 
	 * @return
	 */
	protected SccpAddress getServiceCenterSccpAddress(int networkId) {
        if (networkId == 0) {
            if (this.serviceCenterSCCPAddress == null) {
                this.serviceCenterSCCPAddress = MessageUtil.getSccpAddress(sccpParameterFact, smscPropertiesManagement.getServiceCenterGt(),
                        NatureOfAddress.INTERNATIONAL.getValue(), NumberingPlan.ISDN_TELEPHONY.getValue(), smscPropertiesManagement.getServiceCenterSsn(),
                        smscPropertiesManagement.getGlobalTitleIndicator(), smscPropertiesManagement.getTranslationType());
            }
            return this.serviceCenterSCCPAddress;
        } else {
            return MessageUtil.getSccpAddress(sccpParameterFact, smscPropertiesManagement.getServiceCenterGt(networkId),
                    NatureOfAddress.INTERNATIONAL.getValue(), NumberingPlan.ISDN_TELEPHONY.getValue(), smscPropertiesManagement.getServiceCenterSsn(),
                    smscPropertiesManagement.getGlobalTitleIndicator(), smscPropertiesManagement.getTranslationType());
        }
	}

	protected ISDNAddressString getCalledPartyISDNAddressString(String destinationAddress, int ton, int npi) {
		return this.mapParameterFactory.createISDNAddressString(AddressNature.getInstance(ton),
				org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan.getInstance(npi), destinationAddress);
	}

    protected void onDeliveryError(SmsSet smsSet, ErrorAction errorAction, ErrorCode smStatus, String reason,
            boolean removeSmsSet, MAPErrorMessage errMessage, boolean isImsiVlrReject) {
        smscStatAggregator.updateMsgOutFailedAll();

        PersistenceRAInterface pers = this.getStore();

        long currentMsgNum = this.doGetCurrentMsgNum();
		Sms smsa = smsSet.getSms(currentMsgNum);
        if (smsa != null) {
            CdrGenerator.generateCdr(smsa, CdrGenerator.CDR_TEMP_FAILED, reason, smscPropertiesManagement.getGenerateReceiptCdr(),
                    MessageUtil.isNeedWriteArchiveMessage(smsa, smscPropertiesManagement.getGenerateCdr()));
        }

		StringBuilder sb = new StringBuilder();
		sb.append("onDeliveryError: errorAction=");
        sb.append(errorAction);
        sb.append(", smStatus=");
        sb.append(smStatus);
        sb.append(", targetId=");
        sb.append(smsSet.getTargetId());
		sb.append(", smsSet=");
		sb.append(smsSet);
        sb.append(", reason=");
        sb.append(reason);
		if (this.logger.isInfoEnabled())
			this.logger.info(sb.toString());

        // sending of a failure response for transactional mode
        MessageDeliveryResultResponseInterface.DeliveryFailureReason delReason = MessageDeliveryResultResponseInterface.DeliveryFailureReason.destinationUnavalable;
        if (errorAction == ErrorAction.temporaryFailure)
            delReason = MessageDeliveryResultResponseInterface.DeliveryFailureReason.temporaryNetworkError;
        if (errorAction == ErrorAction.permanentFailure)
            delReason = MessageDeliveryResultResponseInterface.DeliveryFailureReason.permanentNetworkError;
        for (long i1 = currentMsgNum; i1 < smsSet.getSmsCount(); i1++) {
            Sms sms = smsSet.getSms(i1);
            if (sms != null) {
                if (sms.getMessageDeliveryResultResponse() != null) {
                    sms.getMessageDeliveryResultResponse().responseDeliveryFailure(delReason, errMessage);
                    sms.setMessageDeliveryResultResponse(null);
                }
            }
        }

		ArrayList lstFailured = new ArrayList();

		SMDeliveryOutcome smDeliveryOutcome = null;
		TargetAddress lock = pers.obtainSynchroObject(new TargetAddress(smsSet));
		synchronized (lock) {
			try {
				Date curDate = new Date();
				try {
                    if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                        pers.setDeliveryFailure(smsSet, smStatus, curDate);
                    } else {
                        smsSet.setStatus(smStatus);
                        if (removeSmsSet)
                            SmsSetCache.getInstance().removeProcessingSmsSet(smsSet.getTargetId());
                    }
					this.decrementDeliveryActivityCount();

					long smsCnt;
                    if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                        // first of all we are removing messages that delivery
                        // period is over
                        smsCnt = smsSet.getSmsCount();
                        int goodMsgCnt = 0;
                        int removedMsgCnt = 0;
                        for (long i1 = currentMsgNum; i1 < smsCnt; i1++) {
                            Sms sms = smsSet.getSms(i1);
                            if (sms != null) {
                                if (sms.getValidityPeriod().before(curDate)) {
                                    pers.archiveFailuredSms(sms);
                                    lstFailured.add(sms);
                                    removedMsgCnt++;
                                } else {
                                    goodMsgCnt++;
                                }
                            }
                        }

                        if (goodMsgCnt == 0 || removedMsgCnt > 0) {
                            // no more messages to send
                            // firstly we search for new uploaded message
                            pers.fetchSchedulableSms(smsSet, false);
                            if (smsSet.getSmsCount() == 0)
                                errorAction = ErrorAction.permanentFailure;
                        }
                    } else {
                    }

					switch (errorAction) {
					case subscriberBusy:
						this.rescheduleSmsSet(smsSet, true, pers, currentMsgNum, lstFailured);
						break;

					case memoryCapacityExceededFlag:
						smDeliveryOutcome = SMDeliveryOutcome.memoryCapacityExceeded;
						this.rescheduleSmsSet(smsSet, false, pers, currentMsgNum, lstFailured);
						break;

					case mobileNotReachableFlag:
						smDeliveryOutcome = SMDeliveryOutcome.absentSubscriber;
						this.rescheduleSmsSet(smsSet, false, pers, currentMsgNum, lstFailured);
						break;

					case notReachableForGprs:
						smDeliveryOutcome = SMDeliveryOutcome.absentSubscriber;
						this.rescheduleSmsSet(smsSet, false, pers, currentMsgNum, lstFailured);
						break;

					case temporaryFailure:
						this.rescheduleSmsSet(smsSet, false, pers, currentMsgNum, lstFailured);
						break;

					case permanentFailure:
						smsCnt = smsSet.getSmsCount();
						for (long i1 = currentMsgNum; i1 < smsCnt; i1++) {
							Sms sms = smsSet.getSms(i1);
							if (sms != null) {
								lstFailured.add(sms);
							}
						}
						this.freeSmsSetFailured(smsSet, pers, currentMsgNum);
						break;
					}

				} catch (PersistenceException e) {
					this.logger.severe("PersistenceException when onDeliveryError()" + e.getMessage(), e);
				}

			} finally {
				pers.releaseSynchroObject(lock);
			}
		}

		if ( errorAction != ErrorAction.permanentFailure &&
						!smscPropertiesManagement.getReceiptsDisabling() ) {
				doIntermediateReceipts(smsSet, pers, currentMsgNum, lstFailured);
		}
        for (Sms sms : lstFailured) {
            CdrGenerator.generateCdr(sms, (isImsiVlrReject ? CdrGenerator.CDR_FAILED_IMSI : CdrGenerator.CDR_FAILED), reason,
                    smscPropertiesManagement.getGenerateReceiptCdr(),
                    MessageUtil.isNeedWriteArchiveMessage(sms, smscPropertiesManagement.getGenerateCdr()));

            if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
            } else {
                sms.setDeliveryDate(new Date());
                try {
                    if (MessageUtil.isNeedWriteArchiveMessage(sms, smscPropertiesManagement.getGenerateArchiveTable())) {
                        pers.c2_createRecordArchive(sms);
                    }
                } catch (PersistenceException e) {
                    this.logger.severe("PersistenceException when freeSmsSetFailured(SmsSet smsSet) - c2_createRecordArchive(sms)" + e.getMessage(), e);
                }
            }

            // mproc rules applying for delivery phase
            MProcResult mProcResult = MProcManagement.getInstance().applyMProcDelivery(sms, true);
            FastList addedMessages = mProcResult.getMessageList();
            if (addedMessages != null) {
                for (FastList.Node n = addedMessages.head(), end = addedMessages.tail(); (n = n.getNext()) != end;) {
                    Sms smst = n.getValue();
                    TargetAddress ta = new TargetAddress(smst.getSmsSet().getDestAddrTon(), smst.getSmsSet().getDestAddrNpi(),
                            smst.getSmsSet().getDestAddr(), smst.getSmsSet().getNetworkId());
                    TargetAddress lock2 = SmsSetCache.getInstance().addSmsSet(ta);
                    try {
                        synchronized (lock2) {
                            if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                            } else {
                                boolean storeAndForwMode = MessageUtil.isStoreAndForward(smst);
                                if (!storeAndForwMode) {
                                    try {
                                        this.scheduler.injectSmsOnFly(smst.getSmsSet(), true);
                                    } catch (Exception e) {
                                        this.logger.severe(
                                                "Exception when runnung injectSmsOnFly() for applyMProcDelivery created messages in onDeliveryError(): "
                                                        + e.getMessage(), e);
                                    }
                                } else {
                                    if (smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast) {
                                        try {
                                            smst.setStoringAfterFailure(true);
                                            this.scheduler.injectSmsOnFly(smst.getSmsSet(), true);
                                        } catch (Exception e) {
                                            this.logger.severe(
                                                    "Exception when runnung injectSmsOnFly() for applyMProcDelivery created messages in onDeliveryError(): "
                                                            + e.getMessage(), e);
                                        }
                                    } else {
                                        smst.setStored(true);
                                        this.scheduler.setDestCluster(smst.getSmsSet());
                                        try {
                                            pers.c2_scheduleMessage_ReschedDueSlot(
                                                    smst,
                                                    smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast,
                                                    true);
                                        } catch (PersistenceException e) {
                                            this.logger.severe(
                                                    "PersistenceException when onDeliveryError(SmsSet smsSet) - adding applyMProcDelivery created messages"
                                                            + e.getMessage(), e);
                                        }
                                    }
                                }
                            }
                        }
                    } finally {
                        SmsSetCache.getInstance().removeSmsSet(lock2);
                    }
                }
            }

            // adding an error receipt if it is needed
            int registeredDelivery = sms.getRegisteredDelivery();
            if (!smscPropertiesManagement.getReceiptsDisabling() && MessageUtil.isReceiptOnFailure(registeredDelivery)) {
                TargetAddress ta = new TargetAddress(sms.getSourceAddrTon(), sms.getSourceAddrNpi(), sms.getSourceAddr(), smsSet.getNetworkId());
                lock = SmsSetCache.getInstance().addSmsSet(ta);
                try {
                    synchronized (lock) {
                        try {
                            Sms receipt;
                            if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                                receipt = MessageUtil.createReceiptSms(sms, false);
                                SmsSet backSmsSet = pers.obtainSmsSet(ta);
                                receipt.setSmsSet(backSmsSet);
                                receipt.setStored(true);
                                pers.createLiveSms(receipt);
                                pers.setNewMessageScheduled(receipt.getSmsSet(),
                                        MessageUtil.computeDueDate(MessageUtil.computeFirstDueDelay(smscPropertiesManagement.getFirstDueDelay())));
                            } else {
                                receipt = MessageUtil.createReceiptSms(sms, false, ta, smscPropertiesManagement.getOrigNetworkIdForReceipts());
                                boolean storeAndForwMode = MessageUtil.isStoreAndForward(sms);
                                if (!storeAndForwMode) {
                                    try {
                                        this.scheduler.injectSmsOnFly(receipt.getSmsSet(), true);
                                    } catch (Exception e) {
                                        this.logger.severe("Exception when runnung injectSmsOnFly() for receipt in onDeliveryError(): " + e.getMessage(), e);
                                    }
                                } else {
                                    if (smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast) {
                                        try {
                                            receipt.setStoringAfterFailure(true);
                                            this.scheduler.injectSmsOnFly(receipt.getSmsSet(), true);
                                        } catch (Exception e) {
                                            this.logger
                                                    .severe("Exception when runnung injectSmsOnFly() for receipt in onDeliveryError(): " + e.getMessage(), e);
                                        }
                                    } else {
                                        receipt.setStored(true);
                                        this.scheduler.setDestCluster(receipt.getSmsSet());
                                        pers.c2_scheduleMessage_ReschedDueSlot(receipt,
                                                smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast, true);
                                    }
                                }
                            }
                            this.logger.info("Adding an error receipt: source=" + receipt.getSourceAddr() + ", dest=" + receipt.getSmsSet().getDestAddr());
                        } catch (PersistenceException e) {
                            this.logger.severe("PersistenceException when freeSmsSetFailured(SmsSet smsSet) - adding delivery receipt" + e.getMessage(), e);
                        }
                    }
                } finally {
                    SmsSetCache.getInstance().removeSmsSet(lock);
                }
            }
		}

		if (smDeliveryOutcome != null && smsSet.getSmsCount() > lstFailured.size()) {
            this.setupReportSMDeliveryStatusRequest(smsSet.getDestAddr(), smsSet.getDestAddrTon(), smsSet.getDestAddrNpi(), smDeliveryOutcome,
                    smsSet.getTargetId(), smsSet.getNetworkId());
		}
	}

	private void doIntermediateReceipts(SmsSet smsSet, PersistenceRAInterface pers, long currentMsgNum, ArrayList lstFailured) {
		TargetAddress lock;
		long smsCnt = smsSet.getSmsCount();
		for (long i1 = currentMsgNum; i1 < smsCnt; i1++) {
            Sms sms = smsSet.getSms(i1);
            int registeredDelivery = sms.getRegisteredDelivery();
            if (smscPropertiesManagement.getEnableIntermediateReceipts()
                    && MessageUtil.isReceiptIntermediate(registeredDelivery) && lstFailured.indexOf(sms) == -1) {
                TargetAddress ta = new TargetAddress(sms.getSourceAddrTon(), sms.getSourceAddrNpi(), sms.getSourceAddr(), smsSet.getNetworkId());
                lock = SmsSetCache.getInstance().addSmsSet(ta);
                try {
                    synchronized (lock) {
                        try {
                            Sms receipt;
                            if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                                receipt = MessageUtil.createReceiptSms(sms, false);
                                SmsSet backSmsSet = pers.obtainSmsSet(ta);
                                receipt.setSmsSet(backSmsSet);
                                receipt.setStored(true);
                                pers.createLiveSms(receipt);
                                pers.setNewMessageScheduled(receipt.getSmsSet(),
                                        MessageUtil.computeDueDate(MessageUtil.computeFirstDueDelay(smscPropertiesManagement.getFirstDueDelay())));
                            } else {
                                receipt = MessageUtil.createReceiptSms(sms, false, ta, smscPropertiesManagement.getOrigNetworkIdForReceipts(),null,true);
                                boolean storeAndForwMode = MessageUtil.isStoreAndForward(sms);
                                if (!storeAndForwMode) {
                                    try {
                                        this.scheduler.injectSmsOnFly(receipt.getSmsSet(), true);
                                    } catch (Exception e) {
                                        this.logger.severe("Exception when runnung injectSmsOnFly() for receipt in onDeliveryError(): " + e.getMessage(), e);
                                    }
                                } else {
                                    if (smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast) {
                                        try {
                                            receipt.setStoringAfterFailure(true);
                                            this.scheduler.injectSmsOnFly(receipt.getSmsSet(), true);
                                        } catch (Exception e) {
                                            this.logger
                                                    .severe("Exception when runnung injectSmsOnFly() for receipt in onDeliveryError(): " + e.getMessage(), e);
                                        }
                                    } else {
                                        receipt.setStored(true);
                                        this.scheduler.setDestCluster(receipt.getSmsSet());
                                        pers.c2_scheduleMessage_ReschedDueSlot(receipt,
                                                smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast, true);
                                    }
                                }
                            }
                            this.logger.info("Adding an error receipt: source=" + receipt.getSourceAddr() + ", dest=" + receipt.getSmsSet().getDestAddr());
                        } catch (PersistenceException e) {
                            this.logger.severe("PersistenceException when freeSmsSetFailured(SmsSet smsSet) - adding delivery receipt" + e.getMessage(), e);
                        }
                    }
                } finally {
                    SmsSetCache.getInstance().removeSmsSet(lock);
                }
            }
        }
	}

    protected void onImsiDrop(Sms sms, String imsi, ISDNAddressString nnn) {
//        smscStatAggregator.updateMsgOutFailedAll();

        PersistenceRAInterface pers = this.getStore();

        StringBuilder sb = new StringBuilder();
        sb.append("onImsiDrop: targetId=");
        sb.append(sms.getSmsSet().getTargetId());
        sb.append(", sms=");
        sb.append(sms);
        if (this.logger.isInfoEnabled())
            this.logger.info(sb.toString());

        // sending of a failure response for transactional mode
        MessageDeliveryResultResponseInterface.DeliveryFailureReason delReason = MessageDeliveryResultResponseInterface.DeliveryFailureReason.destinationUnavalable;
        if (sms.getMessageDeliveryResultResponse() != null) {
            sms.getMessageDeliveryResultResponse().responseDeliveryFailure(delReason, null);
            sms.setMessageDeliveryResultResponse(null);
        }

        CdrGenerator.generateCdr(sms, CdrGenerator.CDR_FAILED_IMSI,
                "Sri-ImsiRequest: incoming messages are dropped by mProc rules",
                smscPropertiesManagement.getGenerateReceiptCdr(),
                MessageUtil.isNeedWriteArchiveMessage(sms, smscPropertiesManagement.getGenerateCdr()));

        try {
            pers.c2_updateInSystem(sms, DBOperations_C2.IN_SYSTEM_SENT,
                    smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast);
            sms.getSmsSet().setStatus(ErrorCode.MPROC_SRI_REQUEST_DROP);
            sms.setDeliveryDate(new Date());
            if (MessageUtil.isNeedWriteArchiveMessage(sms, smscPropertiesManagement.getGenerateArchiveTable())) {
                pers.c2_createRecordArchive(sms);
            }
        } catch (PersistenceException e) {
            this.logger.severe("PersistenceException when onImsiDrop() - c2_createRecordArchive" + e.getMessage(), e);
        }

        // adding an error receipt if it is needed
        int registeredDelivery = sms.getRegisteredDelivery();
        if (!smscPropertiesManagement.getReceiptsDisabling() && MessageUtil.isReceiptOnFailure(registeredDelivery)) {
            TargetAddress ta = new TargetAddress(sms.getSourceAddrTon(), sms.getSourceAddrNpi(), sms.getSourceAddr(), sms
                    .getSmsSet().getNetworkId());
            TargetAddress lock = SmsSetCache.getInstance().addSmsSet(ta);
            try {
                synchronized (lock) {
                    try {
                        Sms receipt;
                        StringBuilder extraString = new StringBuilder();
                        extraString.append(" imsi:");
                        extraString.append(imsi);
                        extraString.append(" nnn_digits:");
                        extraString.append(nnn.getAddress());
                        extraString.append(" nnn_an:");
                        extraString.append(nnn.getAddressNature().getIndicator());
                        extraString.append(" nnn_np:");
                        extraString.append(nnn.getNumberingPlan().getIndicator());
                        if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                            receipt = MessageUtil.createReceiptSms(sms, false);
                            SmsSet backSmsSet = pers.obtainSmsSet(ta);
                            receipt.setSmsSet(backSmsSet);
                            receipt.setStored(true);
                            pers.createLiveSms(receipt);
                            pers.setNewMessageScheduled(receipt.getSmsSet(), MessageUtil.computeDueDate(MessageUtil
                                    .computeFirstDueDelay(smscPropertiesManagement.getFirstDueDelay())));
                        } else {
                            receipt = MessageUtil.createReceiptSms(sms, false, ta,
                                    smscPropertiesManagement.getOrigNetworkIdForReceipts(), extraString.toString());
                            boolean storeAndForwMode = MessageUtil.isStoreAndForward(sms);
                            if (!storeAndForwMode) {
                                try {
                                    this.scheduler.injectSmsOnFly(receipt.getSmsSet(), true);
                                } catch (Exception e) {
                                    this.logger.severe(
                                            "Exception when runnung injectSmsOnFly() for receipt in onImsiDrop(): "
                                                    + e.getMessage(), e);
                                }
                            } else {
                                if (smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast) {
                                    try {
                                        receipt.setStoringAfterFailure(true);
                                        this.scheduler.injectSmsOnFly(receipt.getSmsSet(), true);
                                    } catch (Exception e) {
                                        this.logger.severe(
                                                "Exception when runnung injectSmsOnFly() for receipt in onImsiDrop(): "
                                                        + e.getMessage(), e);
                                    }
                                } else {
                                    receipt.setStored(true);
                                    this.scheduler.setDestCluster(receipt.getSmsSet());
                                    pers.c2_scheduleMessage_ReschedDueSlot(receipt,
                                            smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast, true);
                                }
                            }
                        }
                        this.logger.info("Adding an error receipt: source=" + receipt.getSourceAddr() + ", dest="
                                + receipt.getSmsSet().getDestAddr());
                    } catch (PersistenceException e) {
                        this.logger.severe(
                                "PersistenceException when onImsiDrop(Set) - adding delivery receipt"
                                        + e.getMessage(), e);
                    }
                }
            } finally {
                SmsSetCache.getInstance().removeSmsSet(lock);
            }
        }
    }

	public abstract void doSetSmsSubmitData(SmsSubmitData smsDeliveryData);

	public abstract SmsSubmitData doGetSmsSubmitData();

	public abstract void doSetCurrentMsgNum(long currentMsgNum);

	public abstract long doGetCurrentMsgNum();

	public abstract void doSetInformServiceCenterContainer(InformServiceCenterContainer informServiceCenterContainer);

	public abstract InformServiceCenterContainer doGetInformServiceCenterContainer();

	/**
	 * Mark a message that its delivery has been started
	 * 
	 * @param sms
	 */
	protected void startMessageDelivery(Sms sms) {

		try {
			this.getStore().setDeliveryStart(sms);
		} catch (PersistenceException e) {
			this.logger.severe("PersistenceException when setDeliveryStart(sms)" + e.getMessage(), e);
		}
	}

	/**
	 * remove smsSet from LIVE database after all messages has been delivered
	 * 
	 * @param smsSet
	 */
	protected void freeSmsSetSucceded(SmsSet smsSet, PersistenceRAInterface pers) {
        try {
            this.decrementDeliveryActivityCount();
            if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                Date lastDelivery = new Date();
                pers.setDeliverySuccess(smsSet, lastDelivery);

                if (!pers.deleteSmsSet(smsSet)) {
                    Date newDueDate = MessageUtil.computeDueDate(MessageUtil.computeFirstDueDelay(smscPropertiesManagement.getFirstDueDelay()));
                    pers.fetchSchedulableSms(smsSet, false);
                    newDueDate = MessageUtil.checkScheduleDeliveryTime(smsSet, newDueDate);
                    pers.setNewMessageScheduled(smsSet, newDueDate);
                }
            } else {
                smsSet.setStatus(ErrorCode.SUCCESS);
                SmsSetCache.getInstance().removeProcessingSmsSet(smsSet.getTargetId());
            }
        } catch (PersistenceException e) {
            this.logger.severe("PersistenceException when freeSmsSetSucceded(SmsSet smsSet)" + e.getMessage(), e);
        }
	}

	/**
	 * remove smsSet from LIVE database after permanent delivery failure
	 * 
	 * @param smsSet
	 * @param pers
	 */
	protected void freeSmsSetFailured(SmsSet smsSet, PersistenceRAInterface pers, long currentMsgNum) {

		TargetAddress lock = pers.obtainSynchroObject(new TargetAddress(smsSet));
		try {
			synchronized (lock) {
				try {
                    if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                        pers.fetchSchedulableSms(smsSet, false);
                        long cnt = smsSet.getSmsCount();
                        for (int i1 = 0; i1 < cnt; i1++) {
                            Sms sms = smsSet.getSms(i1);
                            pers.archiveFailuredSms(sms);
                        }

                        pers.deleteSmsSet(smsSet);
                    } else {
                        for (long i1 = currentMsgNum; i1 < smsSet.getSmsCount(); i1++) {
                            Sms sms = smsSet.getSms(i1);
                            pers.c2_updateInSystem(sms, DBOperations_C2.IN_SYSTEM_SENT,
                                    smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast);
                            sms.setDeliveryDate(new Date());
                            if (MessageUtil.isNeedWriteArchiveMessage(sms, smscPropertiesManagement.getGenerateArchiveTable())) {
                                pers.c2_createRecordArchive(sms);
                            }
                        }
                    }
				} catch (PersistenceException e) {
					this.logger.severe("PersistenceException when freeSmsSetFailured(SmsSet smsSet)" + e.getMessage(),
							e);
				}
			}
		} finally {
			pers.releaseSynchroObject(lock);
		}
	}

	/**
	 * make new schedule time for smsSet after temporary failure
	 * 
	 * @param smsSet
	 */
	protected void rescheduleSmsSet(SmsSet smsSet, boolean busySuscriber, PersistenceRAInterface pers, long currentMsgNum, ArrayList lstFailured) {

		TargetAddress lock = pers.obtainSynchroObject(new TargetAddress(smsSet));
		try {
			synchronized (lock) {

				try {
					int prevDueDelay = smsSet.getDueDelay();
					int newDueDelay;
					if (busySuscriber) {
                        newDueDelay = MessageUtil.computeDueDelaySubscriberBusy(smscPropertiesManagement.getSubscriberBusyDueDelay());
					} else {
                        newDueDelay = MessageUtil.computeNextDueDelay(prevDueDelay, smscPropertiesManagement.getSecondDueDelay(),
                                smscPropertiesManagement.getDueDelayMultiplicator(), smscPropertiesManagement.getMaxDueDelay());
					}

					Date newDueDate = new Date(new Date().getTime() + newDueDelay * 1000);

					newDueDate = MessageUtil.checkScheduleDeliveryTime(smsSet, newDueDate);
                    if (smscPropertiesManagement.getDatabaseType() == DatabaseType.Cassandra_1) {
                        pers.setDeliveringProcessScheduled(smsSet, newDueDate, newDueDelay);
                    } else {
                        smsSet.setDueDate(newDueDate);
                        smsSet.setDueDelay(newDueDelay);
                        long dueSlot = this.getStore().c2_getDueSlotForTime(newDueDate);
                        for (long i1 = currentMsgNum; i1 < smsSet.getSmsCount(); i1++) {
                            Sms sms = smsSet.getSms(i1);
                            pers.c2_scheduleMessage_NewDueSlot(sms, dueSlot, lstFailured,
                                    smscPropertiesManagement.getStoreAndForwordMode() == StoreAndForwordMode.fast);
                        }
                    }
				} catch (PersistenceException e) {
					this.logger.severe("PersistenceException when rescheduleSmsSet(SmsSet smsSet)" + e.getMessage(), e);
				}
			}
		} finally {
			pers.releaseSynchroObject(lock);
		}
	}

	/**
	 * Get the Scheduler Activity
	 * 
	 * @return
	 */
	protected ActivityContextInterface getSchedulerActivityContextInterface() {
		ActivityContextInterface[] acis = this.sbbContext.getActivities();
		for (int count = 0; count < acis.length; count++) {
			ActivityContextInterface aci = acis[count];
			Object activity = aci.getActivity();
			if (activity instanceof SchedulerActivity) {
				return aci;
			}
		}

		return null;
	}

	private void decrementDeliveryActivityCount() {
		try {
			ActivityContextInterface schedulerActivityContextInterface = this.getSchedulerActivityContextInterface();
			SchedulerActivity schedulerActivity = (SchedulerActivity) schedulerActivityContextInterface.getActivity();

			schedulerActivity.endActivity();
		} catch (Exception e) {
			this.logger.severe("Error while decrementing DeliveryActivityCount", e);
		}
	}

	public enum ErrorAction {
		subscriberBusy,
		memoryCapacityExceededFlag, // MNRF
		mobileNotReachableFlag, // MNRF
		notReachableForGprs, // MNRG
		permanentFailure,
		temporaryFailure,
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy