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

Java tutorial

Introduction

Here is the source code for org.openiot.gsn.http.rest.PushRemoteWrapper.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 Ali Salehi
 * @author Mehdi Riahi
 * @author Timotee Maret
 * @author Julien Eberle
*/

package org.openiot.gsn.http.rest;

import org.openiot.gsn.beans.ContainerConfig;
import org.openiot.gsn.beans.DataField;
import org.openiot.gsn.beans.StreamElement;
import org.openiot.gsn.wrappers.AbstractWrapper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.openiot.gsn.Main;

import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
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.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.log4j.Logger;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;

public class PushRemoteWrapper extends AbstractWrapper {

    private static final int KEEP_ALIVE_PERIOD = 5000;

    private final transient Logger logger = Logger.getLogger(PushRemoteWrapper.class);

    private final XStream XSTREAM = StreamElement4Rest.getXstream();

    private double uid = -1; //only set for push based delivery(default)

    private RemoteWrapperParamParser initParams;

    private DefaultHttpClient httpclient = new DefaultHttpClient();

    private long lastReceivedTimestamp;

    protected DataField[] structure;

    List<NameValuePair> postParameters;

    public void dispose() {
        NotificationRegistry.getInstance().removeNotification(uid);
    }

    public boolean initialize() {

        try {
            initParams = new RemoteWrapperParamParser(getActiveAddressBean(), true);
            uid = Math.random();

            postParameters = new ArrayList<NameValuePair>();
            postParameters.add(new BasicNameValuePair(PushDelivery.NOTIFICATION_ID_KEY, Double.toString(uid)));
            postParameters.add(
                    new BasicNameValuePair(PushDelivery.LOCAL_CONTACT_POINT, initParams.getLocalContactPoint()));
            // Init the http client
            if (initParams.isSSLRequired()) {
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(new FileInputStream(new File("conf/servertestkeystore")),
                        Main.getContainerConfig().getSSLKeyStorePassword().toCharArray());
                SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
                socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                int sslPort = Main.getContainerConfig().getSSLPort() > 0 ? Main.getContainerConfig().getSSLPort()
                        : ContainerConfig.DEFAULT_SSL_PORT;
                Scheme sch = new Scheme("https", socketFactory, sslPort);
                httpclient.getConnectionManager().getSchemeRegistry().register(sch);
            }
            Scheme plainsch = new Scheme("http", PlainSocketFactory.getSocketFactory(),
                    Main.getContainerConfig().getContainerPort());
            httpclient.getConnectionManager().getSchemeRegistry().register(plainsch);
            //
            lastReceivedTimestamp = initParams.getStartTime();
            structure = registerAndGetStructure();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            NotificationRegistry.getInstance().removeNotification(uid);
            return false;
        }

        return true;
    }

    public DataField[] getOutputFormat() {
        return structure;
    }

    public String getWrapperName() {
        return "Push-Remote Wrapper";
    }

    public DataField[] registerAndGetStructure() throws IOException, ClassNotFoundException {
        // Create the POST request
        HttpPost httpPost = new HttpPost(initParams.getRemoteContactPointEncoded(lastReceivedTimestamp));
        // Add the POST parameters
        httpPost.setEntity(new UrlEncodedFormEntity(postParameters, HTTP.UTF_8));
        //
        httpPost.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.FALSE);
        // Create local execution context
        HttpContext localContext = new BasicHttpContext();
        //
        NotificationRegistry.getInstance().addNotification(uid, this);
        int tries = 0;
        AuthState authState = null;
        //
        while (tries < 2) {
            tries++;
            HttpResponse response = null;
            try {
                // Execute the POST request
                response = httpclient.execute(httpPost, localContext);
                //
                int sc = response.getStatusLine().getStatusCode();
                //
                if (sc == HttpStatus.SC_OK) {
                    logger.debug(new StringBuilder().append("Wants to consume the structure packet from ")
                            .append(initParams.getRemoteContactPoint()));
                    structure = (DataField[]) XSTREAM.fromXML(response.getEntity().getContent());
                    logger.debug("Connection established for: " + initParams.getRemoteContactPoint());
                    break;
                } else {
                    if (sc == HttpStatus.SC_UNAUTHORIZED)
                        authState = (AuthState) localContext.getAttribute(ClientContext.TARGET_AUTH_STATE); // Target host authentication required
                    else if (sc == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED)
                        authState = (AuthState) localContext.getAttribute(ClientContext.PROXY_AUTH_STATE); // Proxy authentication required
                    else {
                        logger.error(new StringBuilder().append("Unexpected POST status code returned: ").append(sc)
                                .append("\nreason: ").append(response.getStatusLine().getReasonPhrase()));
                    }
                    if (authState != null) {
                        if (initParams.getUsername() == null || (tries > 1 && initParams.getUsername() != null)) {
                            logger.error("A valid username/password required to connect to the remote host: "
                                    + initParams.getRemoteContactPoint());
                        } else {

                            AuthScope authScope = authState.getAuthScope();
                            logger.warn(new StringBuilder().append("Setting Credentials for host: ")
                                    .append(authScope.getHost()).append(":").append(authScope.getPort()));
                            Credentials creds = new UsernamePasswordCredentials(initParams.getUsername(),
                                    initParams.getPassword());
                            httpclient.getCredentialsProvider().setCredentials(authScope, creds);
                        }
                    }
                }
            } catch (RuntimeException ex) {
                // In case of an unexpected exception you may want to abort
                // the HTTP request in order to shut down the underlying
                // connection and release it back to the connection manager.
                logger.warn("Aborting the HTTP POST request.");
                httpPost.abort();
                throw ex;
            } finally {
                if (response != null && response.getEntity() != null) {
                    response.getEntity().consumeContent();
                }
            }
        }

        if (structure == null)
            throw new RuntimeException("Cannot connect to the remote host.");

        return structure;
    }

    public boolean manualDataInsertion(String Xstream4Rest) {
        logger.debug(new StringBuilder().append("Received Stream Element at the push wrapper."));
        try {

            StreamElement4Rest se = (StreamElement4Rest) XSTREAM.fromXML(Xstream4Rest);
            StreamElement streamElement = se.toStreamElement();

            // If the stream element is out of order, we accept the stream element and wait for the next (update the last received time and return true)
            if (isOutOfOrder(streamElement)) {
                lastReceivedTimestamp = streamElement.getTimeStamp();
                return true;
            }
            // Otherwise, we first try to insert the stream element.
            // If the stream element was inserted succesfully, we wait for the next,
            // otherwise, we return false.
            boolean status = postStreamElement(streamElement);
            if (status)
                lastReceivedTimestamp = streamElement.getTimeStamp();
            return status;
        } catch (SQLException e) {
            logger.warn(e.getMessage(), e);
            return false;
        } catch (XStreamException e) {
            logger.warn(e.getMessage(), e);
            return false;
        }
    }

    public void run() {
        HttpPost httpPost = new HttpPost(initParams.getRemoteContactPointEncoded(lastReceivedTimestamp));
        //
        httpPost.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.FALSE);
        //
        HttpResponse response = null; //This is acting as keep alive.
        //
        while (isActive()) {
            try {
                Thread.sleep(KEEP_ALIVE_PERIOD);
                httpPost.setEntity(new UrlEncodedFormEntity(postParameters, HTTP.UTF_8));
                response = null;
                response = httpclient.execute(httpPost);
                int status = response.getStatusLine().getStatusCode();
                if (status != RestStreamHanlder.SUCCESS_200) {
                    logger.error("Cant register to the remote client, retrying in:" + (KEEP_ALIVE_PERIOD / 1000)
                            + " seconds.");
                    structure = registerAndGetStructure();
                }
            } catch (Exception e) {
                logger.warn(e.getMessage(), e);
            } finally {
                if (response != null) {
                    try {
                        response.getEntity().getContent().close();
                    } catch (Exception e) {
                        logger.warn(e.getMessage(), e);
                    }
                }
            }
        }
    }
}