org.mobicents.applications.ussd.examples.http.push.HTTPPush.java Source code

Java tutorial

Introduction

Here is the source code for org.mobicents.applications.ussd.examples.http.push.HTTPPush.java

Source

/*
 * 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.applications.ussd.examples.http.push;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Date;

import javolution.util.FastList;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.HttpParams;
import org.apache.http.params.SyncBasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContext;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContextName;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContextVersion;
import org.mobicents.protocols.ss7.map.api.MAPException;
import org.mobicents.protocols.ss7.map.api.MAPMessage;
import org.mobicents.protocols.ss7.map.api.MAPMessageType;
import org.mobicents.protocols.ss7.map.api.datacoding.CBSDataCodingScheme;
import org.mobicents.protocols.ss7.map.api.primitives.AddressNature;
import org.mobicents.protocols.ss7.map.api.primitives.AlertingLevel;
import org.mobicents.protocols.ss7.map.api.primitives.AlertingPattern;
import org.mobicents.protocols.ss7.map.api.primitives.ISDNAddressString;
import org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan;
import org.mobicents.protocols.ss7.map.api.primitives.USSDString;
import org.mobicents.protocols.ss7.map.api.service.supplementary.UnstructuredSSNotifyRequest;
import org.mobicents.protocols.ss7.map.api.service.supplementary.UnstructuredSSRequest;
import org.mobicents.protocols.ss7.map.api.service.supplementary.UnstructuredSSResponse;
import org.mobicents.protocols.ss7.map.datacoding.CBSDataCodingSchemeImpl;
import org.mobicents.protocols.ss7.map.dialog.MAPUserAbortChoiceImpl;
import org.mobicents.protocols.ss7.map.primitives.AlertingPatternImpl;
import org.mobicents.protocols.ss7.map.primitives.ISDNAddressStringImpl;
import org.mobicents.protocols.ss7.map.primitives.USSDStringImpl;
import org.mobicents.protocols.ss7.map.service.supplementary.UnstructuredSSNotifyRequestImpl;
import org.mobicents.protocols.ss7.map.service.supplementary.UnstructuredSSRequestImpl;
import org.mobicents.protocols.ss7.tcap.api.MessageType;
import org.mobicents.ussdgateway.EventsSerializeFactory;
import org.mobicents.ussdgateway.XmlMAPDialog;

/**
 * @author baranowb
 * 
 */
public class HTTPPush implements HTTPPushMBean {

    private static final Logger logger = Logger.getLogger(HTTPPush.class);
    // default
    private String targetURI = "http://localhost:8080/mobicents";
    private String isdn = "1111";

    private EventsSerializeFactory serializer = new EventsSerializeFactory();
    private StringBuilder status = new StringBuilder();
    private static long ID = 0;

    // some defs
    private static final CBSDataCodingScheme CBS_CODDING_SCHEME = new CBSDataCodingSchemeImpl(15);
    private static final AlertingPattern ALERTING_PATTERN = new AlertingPatternImpl(AlertingLevel.Level1);
    private static final String ANSWER_NTFY = "2";

    // session
    private XmlMAPDialog dialog;
    private HttpContext context;

    // client
    private HttpClient httpClient;

    private CookieStore cookieStore = null;

    private final MAPApplicationContext appCtx = MAPApplicationContext.getInstance(
            MAPApplicationContextName.networkUnstructuredSsContext, MAPApplicationContextVersion.version2);

    /**
      * 
      */
    public HTTPPush() {
        super();
        HttpParams params = new SyncBasicHttpParams();
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
        schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
        ThreadSafeClientConnManager threadSafeClientConnManager = new ThreadSafeClientConnManager(schemeRegistry);
        threadSafeClientConnManager.setMaxTotal(1000);

        httpClient = new DefaultHttpClient(threadSafeClientConnManager, params);
    }

    @Override
    public void setTargetUri(String uri) {
        this.targetURI = uri;

    }

    @Override
    public String getTargetUri() {
        return this.targetURI;
    }

    @Override
    public String getIsdn() {
        return isdn;
    }

    @Override
    public void setIsdn(String isdn) {
        this.isdn = isdn;
    }

    @Override
    public void reset() {
        // TODO: try to end gracefully, ie send term or something
        this.dialog = null;
        this.status = new StringBuilder();
        this.context = null;
    }

    @Override
    public void sendRequest(String ussdRequest, boolean emptyDialogHandshake, int invokeTimeout, String userData)
            throws Exception {
        ISDNAddressString isdnAddressString = getISDNAddressString();
        USSDString ussdStr = getUSSDString(ussdRequest);
        UnstructuredSSRequest unstructuredSSRequestIndication = new UnstructuredSSRequestImpl(CBS_CODDING_SCHEME,
                ussdStr, ALERTING_PATTERN, isdnAddressString);

        // lets be a good citizen
        if (this.dialog == null) {
            this.establishSession();
            this.dialog = new XmlMAPDialog(appCtx, null, null, 0l, 0l, null, null);
            this.dialog.setCustomInvokeTimeOut(invokeTimeout);
            this.dialog.setEmptyDialogHandshake(emptyDialogHandshake);
            this.dialog.setTCAPMessageType(MessageType.Begin);
            addStatusEntry("Created dialog: '" + this.dialog);
        } else {
            this.dialog.reset();
            this.dialog.setTCAPMessageType(MessageType.Continue);
            addStatusEntry("Sending on existing dialog: '" + this.dialog);
        }

        if (userData != null) {
            this.dialog.setUserObject(userData);
        }

        this.dialog.addMAPMessage(unstructuredSSRequestIndication);
        byte[] serialized = this.serializer.serialize(this.dialog);
        // send
        addStatusEntry("Sending UnstructuredSSRequest");
        HttpResponse response = send(serialized);
        handleResponse(response);
    }

    @Override
    public void sendNotify(String ussdRequest, boolean emptyDialogHandshake, int invokeTimeout, String userData)
            throws Exception {
        ISDNAddressString isdnAddressString = getISDNAddressString();
        USSDString ussdStr = getUSSDString(ussdRequest);
        UnstructuredSSNotifyRequest unstructuredSSNotifyRequest = new UnstructuredSSNotifyRequestImpl(
                CBS_CODDING_SCHEME, ussdStr, ALERTING_PATTERN, isdnAddressString);

        // lets be a good citizen
        if (this.dialog == null) {
            this.establishSession();
            this.dialog = new XmlMAPDialog(appCtx, null, null, 0l, 0l, null, null);
            this.dialog.setEmptyDialogHandshake(emptyDialogHandshake);
            this.dialog.setCustomInvokeTimeOut(invokeTimeout);
            this.dialog.setTCAPMessageType(MessageType.Begin);
            addStatusEntry("Created dialog: '" + this.dialog);
        } else {
            this.dialog.reset();
            this.dialog.setTCAPMessageType(MessageType.Continue);
            addStatusEntry("Sending on existing dialog: '" + this.dialog);
        }

        if (userData != null) {
            this.dialog.setUserObject(userData);
        }

        this.dialog.addMAPMessage(unstructuredSSNotifyRequest);
        byte[] serialized = this.serializer.serialize(this.dialog);
        addStatusEntry("Sending UnstructuredSSNotifyRequest");
        HttpResponse response = send(serialized);
        handleResponse(response);
    }

    @Override
    public String getStatus() {
        return this.status.toString();
    }

    @Override
    public void abort() throws Exception {
        if (this.dialog == null) {
            throw new Exception("There is no Dialog established yet");
        }

        MAPUserAbortChoiceImpl abort = new MAPUserAbortChoiceImpl();
        abort.setUserSpecificReason();

        this.dialog.reset();
        this.dialog.setTCAPMessageType(MessageType.Abort);
        this.dialog.abort(abort);

        addStatusEntry("Aborting existing dialog: '" + this.dialog);

        byte[] serialized = this.serializer.serialize(this.dialog);

        HttpResponse response = send(serialized);
        handleResponse(response);
    }

    @Override
    public void close() throws Exception {
        if (this.dialog == null) {
            throw new Exception("There is no Dialog established yet");
        }

        this.dialog.reset();
        this.dialog.setTCAPMessageType(MessageType.End);
        this.dialog.close(false);

        addStatusEntry("Closing existing dialog: '" + this.dialog);

        byte[] serialized = this.serializer.serialize(this.dialog);

        HttpResponse response = send(serialized);
        handleResponse(response);
    }

    protected synchronized long getNewID() {
        return ID++;
    }

    protected USSDString getUSSDString(String msg) throws MAPException {
        return new USSDStringImpl(msg, CBS_CODDING_SCHEME, null);
    }

    protected ISDNAddressString getISDNAddressString() {
        return new ISDNAddressStringImpl(AddressNature.international_number, NumberingPlan.ISDN, isdn);
    }

    protected void addStatusEntry(String entry) {
        Date d = new Date();
        d.setTime(System.currentTimeMillis());
        StringBuilder sb = new StringBuilder();
        sb.append(d.toString()).append(">").append(entry);
        sb.append("\n");
        sb.append("---------------------------------");
        logger.info(sb.toString());
        this.status.append(sb.toString().replaceAll("<", "-").replaceAll(">", "-"));
    }

    protected void establishSession() {
        this.context = new BasicHttpContext();
        CookieStore cookieStore = new BasicCookieStore();
        this.context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
    }

    /**
     * @param serialized
     * @return
     */
    protected HttpResponse send(byte[] serialized) throws Exception {
        HttpUriRequest post = new HttpPost(this.targetURI);
        if (!(post instanceof HttpEntityEnclosingRequestBase)) {
            throw new IOException();
        }
        addStatusEntry("Sending:\n" + new String(serialized));
        ByteArrayEntity entity = new ByteArrayEntity(serialized);
        entity.setContentType("text/xml");
        entity.setContentEncoding(Charset.defaultCharset().toString());
        ((HttpEntityEnclosingRequestBase) post).setEntity(entity);

        return this.httpClient.execute(post, this.context);
    }

    /**
     * Handle response, this checks for choice and sends NTFY if required
     * 
     * @param response
     * @throws Exception
     */
    protected void handleResponse(HttpResponse response) throws Exception {
        if (response.getStatusLine().getStatusCode() != 200) {
            logger.error("Received bad answer: " + response.getStatusLine().getStatusCode() + " <> "
                    + response.getStatusLine().getReasonPhrase());
            return;
        }
        Header[] headers = response.getAllHeaders();
        for (Header h : headers) {
            addStatusEntry(h.getName() + " - " + h.getValue());
        }
        String content = EntityUtils.toString(response.getEntity());

        addStatusEntry("Received response: \n" + content);

        if (content == null || content.trim().equals("")) {
            // received empty response which is ok
            return;
        }

        XmlMAPDialog deserialized = this.serializer.deserialize(content.getBytes());
        this.dialog = deserialized;

        if (this.dialog.getTCAPMessageType() == MessageType.End
                || this.dialog.getTCAPMessageType() == MessageType.Abort) {
            addStatusEntry("Dialog " + this.dialog.getTCAPMessageType().name());
            this.reset();
            return;
        }

        Boolean prearrangedEnd = dialog.getPrearrangedEnd();
        FastList<MAPMessage> capMessages = dialog.getMAPMessages();

        for (FastList.Node<MAPMessage> n = capMessages.head(), end = capMessages
                .tail(); (n = n.getNext()) != end;) {
            MAPMessage message = n.getValue();
            MAPMessageType type = message.getMessageType();
            switch (type) {
            case unstructuredSSRequest_Response:
                UnstructuredSSResponse unstructuredSSResponse = (UnstructuredSSResponse) message;
                USSDString x = unstructuredSSResponse.getUSSDString();
                // TODO: CBS ?
                String s = x.getString(Charset.defaultCharset());
                addStatusEntry("Received response: " + s);
                if (s.equals(ANSWER_NTFY)) {
                    sendNotify("Bye bye", false, 20000, null);
                }
                break;
            case unstructuredSSNotify_Response:
                addStatusEntry("Received NTFY response.");
                break;
            default:
                break;
            }
        }

    }
}