org.openiot.gsn.http.rest.WPPushDelivery.java Source code

Java tutorial

Introduction

Here is the source code for org.openiot.gsn.http.rest.WPPushDelivery.java

Source

/**
*    Copyright (c) 2011-2014, OpenIoT
*   
*    This file is part of OpenIoT.
*
*    OpenIoT 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, version 3 of the License.
*
*    OpenIoT 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 OpenIoT.  If not, see <http://www.gnu.org/licenses/>.
*
*     Contact: OpenIoT mailto: info@openiot.eu
 * @author Julien Eberle
*/

package org.openiot.gsn.http.rest;

import org.openiot.gsn.beans.DataField;
import org.openiot.gsn.beans.StreamElement;

import java.io.IOException;
import java.io.Writer;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.log4j.Logger;

import com.thoughtworks.xstream.XStream;

public class WPPushDelivery implements DeliverySystem {

    //the minimum amount of seconds between two notifications
    //use that to limit the notification rate, especially for testing
    private int DELAY = 60 * 15;

    //1: tile notification, 2: toast notification, 3:raw notification
    private int notificationClass = 3;

    //a message to be used as text or referring to the underlying query 
    private String notificationMessage = "";

    private XStream xstream = StreamElement4Rest.getXstream();

    private boolean isClosed = false;

    private static transient Logger logger = Logger.getLogger(WPPushDelivery.class);

    private HttpPost httpPost;

    private DefaultHttpClient httpclient = new DefaultHttpClient();

    private Writer writer;

    private String lastmessage = "";

    private long lastTimeSent = 0;

    private double notificationId;

    /**
     * Builds a new Windows Phone Push Delivery class
     * @param deliveryContactPoint: the unique url for Windows phone push service
     * @param notificaitonId: the id for identifying the phone on GSN
     * @param writer: where to write back the output structure
     * @param notificationClass: 1: tile notification, 2: toast notification, 3:raw notification
     * @param notificationMessage: a message to be used as text or referring to the underlying query
     */
    public WPPushDelivery(String deliveryContactPoint, double notificaitonId, Writer writer, int notificationClass,
            String notificationMessage) {
        httpPost = new HttpPost(deliveryContactPoint);
        this.notificationClass = notificationClass;
        this.writer = writer;
        this.notificationId = notificaitonId;
        this.notificationMessage = notificationMessage;
    }

    /**
    * Write the structure of the data as xml in the writer given by the constructor.
    * Can be useful in case of raw notification only.
    * @param fields the field structure to write.
    * @throws IOException in case the writer fails.
    */
    public void writeStructure(DataField[] fields) throws IOException {
        String xml = xstream.toXML(fields);
        if (writer == null)
            throw new RuntimeException("The writer structure is null.");
        writer.write(xml);
        writer = null;
    }

    /**
     * Generate the content of the notification according to the notification class 
     * and sends it to the phone. The content of the streamElement can be used in 
     * different ways and this method should be adapted to the specific application.
     * @param se the streamElement
     */
    public boolean writeStreamElement(StreamElement se) {
        String xml = xstream.toXML(new StreamElement4Rest(se)); //raw notification

        if (notificationClass == 2) { //toast notification
            httpPost.setHeader("X-WindowsPhone-Target", "toast");
            xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<wp:Notification xmlns:wp=\"WPNotification\">"
                    + "<wp:Toast>" + "<wp:Text1>GSN Push Service</wp:Text1>" + "<wp:Text2>" + notificationMessage
                    + "</wp:Text2>" + "<wp:Param></wp:Param>" + "</wp:Toast> " + "</wp:Notification>";
        }
        if (notificationClass == 1) { //tile notification
            httpPost.setHeader("X-WindowsPhone-Target", "token");
            xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<wp:Notification xmlns:wp=\"WPNotification\">"
                    + "<wp:Tile ID=\"tile_id\">" + "<wp:BackgroundImage>/Images/front.png</wp:BackgroundImage>"
                    + "<wp:Count></wp:Count>" + "<wp:Title>GSN Push Service</wp:Title>"
                    + "<wp:BackBackgroundImage>/Images/back.png</wp:BackBackgroundImage>" + "<wp:BackTitle>"
                    + notificationMessage + "</wp:BackTitle>" + "<wp:BackContent></wp:BackContent>" + "</wp:Tile> "
                    + "</wp:Notification>";
        }

        if (xml.equalsIgnoreCase(lastmessage)) { // don't send twice the same message
            return true;
        }
        if (se.getTimeStamp() < lastTimeSent + DELAY) {// limit the rate for sending messages
            return true;
        }
        lastmessage = xml;
        lastTimeSent = se.getTimeStamp();
        boolean success = sendData(xml);
        isClosed = !success;
        return success;
    }

    /**
     * No need to keep the connection alive
     */
    public boolean writeKeepAliveStreamElement() {
        return true;
    }

    /**
     * closing all connections
     */
    public void close() {
        httpclient.getConnectionManager().shutdown();
        isClosed = true;
    }

    public boolean isClosed() {
        return isClosed;
    }

    /**
     * Send the given xml string to the contact point.
     * Take action according to the reply from Microsoft's servers (http://msdn.microsoft.com/en-us/library/ff941100%28VS.92%29.aspx).
     * 
     * @param xml
     * @return
     */
    private boolean sendData(String xml) {
        System.out.println(xml);
        try {
            httpPost.setHeader("X-NotificationClass", "" + notificationClass);
            httpPost.setEntity(new StringEntity(xml, HTTP.UTF_8));
            HttpResponse response = httpclient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            String nStatus = "NA";
            String dStatus = "NA";
            String sStatus = "NA";
            response.getEntity().getContent().close(); // releasing the connection to the http client's pool
            if (response.containsHeader("X-NotificationStatus"))
                nStatus = response.getFirstHeader("X-NotificationStatus").getValue();
            if (response.containsHeader("X-DeviceConnectionStatus"))
                dStatus = response.getFirstHeader("X-DeviceConnectionStatus").getValue();
            if (response.containsHeader("X-SubscriptionStatus"))
                sStatus = response.getFirstHeader("X-SubscriptionStatus").getValue();
            logger.warn("Status for client " + notificationId + ":(" + statusCode + ")" + nStatus + ", " + dStatus
                    + "," + sStatus);
            if (statusCode != RestStreamHanlder.SUCCESS_200) {
                return false;
            }
            if (nStatus.equalsIgnoreCase("QueueFull")) {
                lastTimeSent = System.currentTimeMillis() / 1000 + 60 * 60 * 2;
            }
            if (nStatus.equalsIgnoreCase("Suppressed")) {
                return false;
            }
            return true;
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            return false;
        }

    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        WPPushDelivery that = (WPPushDelivery) o;
        if (Double.compare(that.notificationId, notificationId) != 0)
            return false;
        if (httpPost != null ? !httpPost.getURI().equals(that.httpPost.getURI()) : that.httpPost != null)
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        result = httpPost != null ? httpPost.getURI().hashCode() : 0;
        temp = notificationId != +0.0d ? Double.doubleToLongBits(notificationId) : 0L;
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }
}