ActualizadorLocal.Clientes.ClienteDispositivos.java Source code

Java tutorial

Introduction

Here is the source code for ActualizadorLocal.Clientes.ClienteDispositivos.java

Source

/* 
 * Copyright (C) 2013 antares
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ActualizadorLocal.Clientes;

import Entorno.Conectar.Conectar;
import Entorno.Configuracion.Config;
import Entorno.Depuracion.Debug;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import java.sql.SQLException;
import java.sql.Statement;
import javax.net.ssl.*;
import javax.ws.rs.core.MultivaluedMap;
import static java.lang.Thread.sleep;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

/**
 *
 * @author mgarenas, Antonio Fernndez Ares (antares.es@gmail.com)
 *
 */
public class ClienteDispositivos {

    /**
     * Variable de depuracin.
     */
    private Debug _d = new Debug();
    /**
     * Variable de configuracin.
     */
    private static Config _c = new Config();
    /**
     * Variable de conexin HTTP.
     */
    private WebResource webResource;
    /**
     * Variable de conexin HTTP.
     */
    private Client client;
    /**
     * Variable de conexin MYSQL Local.
     */
    Conectar conexion;
    /**
     * Nombres de los parmetros GET de la peticin HTTP.
     */
    String[] queryParamNames;
    /**
     * Valores de los parmetros GET de la peticin HTTP.
     */
    String[] queryParamValues;
    /**
     * Variable de auditora - Nmero de elementos procesados.
     */
    int procesados = 0;
    /**
     * Variable de auditora - Nmero de elementos insertados.
     */
    int insertados = 0;
    /**
     * Variable de gestin peticiones en cach a la BD - Cach.
     */
    String cache = "";
    /**
     * Variable de gestin peticiones en cach a la BD - Tamao actual.
     */
    int cache_size = 0;
    /**
     * Variable de gestin peticiones en cach a la BD - Tamo mximo.
     */
    int MAX_CACHE_SIZE = _c.getInt("db.DISPOSITIVO.MAX_CACHE_SIZE");
    /**
     * Variable de gestin multihebrado - Listado de hebras hijas.
     */
    List<threadSyncDB> l_th = new ArrayList<>();
    /**
     * Variable de gestin multiebrado - Tiempo de espera en caso de error en la
     * hebra.
     */
    public long TIME_SLEEP_IN_ERROR = _c.getInt("db.DISPOSITIVO.TIME_SLEEP_IN_ERROR");
    /**
     * Variable de gestin multiebrado - Nmero de herbas activas simultneas.
     */
    public int MAX_HEBRAS_ACTIVAS_SIMULTANEAS = _c.getInt("db.DISPOSITIVO.MAX_HEBRAS_ACTIVAS_SIMULTANEAS");
    /**
     * Variable de gestin multihebrado - Nmero de intentos de conexin antes
     * de mostar error.
     */
    public int MAX_ERRORES_PARA_NOTIFICACION = _c.getInt("db.DISPOSITIVO.MAX_ERRORES_PARA_NOTIFICACION");
    /**
     * Etiqueta identificadora del proceso.
     */
    public String label;

    /**
     * Constructor por defecto.
     *
     * @param start Fecha de comienzo de los datos
     * @param end Fecha de fin de los datos
     */
    public ClienteDispositivos(String start, String end) {
        queryParamNames = new String[] { "user", "pass", "start", "end", "inc" };
        queryParamValues = new String[] { _c.get("sc.USER"), _c.get("sc.PASS"), start, end, "true" };
        com.sun.jersey.api.client.config.ClientConfig config = new com.sun.jersey.api.client.config.DefaultClientConfig(); // SSL configuration
        // SSL configuration
        config.getProperties().put(com.sun.jersey.client.urlconnection.HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
                new com.sun.jersey.client.urlconnection.HTTPSProperties(getHostnameVerifier(), getSSLContext()));
        client = Client.create(config);

    }

    /**
     * Funcin que estabece la etiqueta asociada al proceso
     *
     * @param label Etiqueta asociada al proceso
     */
    public void setLabel(String label) {
        this.label = label;
    }

    /**
     * Funcin que devuelve el nmero de elementos que han sido procesados. Se
     * considera elemento procesado a aquellos elementos que han sido
     * descargados, independientemente de si han sido o no insertados en la base
     * de datos.
     *
     * @return El nmero de elementos que han sido procesados en la peticin
     */
    public int getProcesados() {
        return procesados;
    }

    /**
     * Funcin que devuelve el nmero de elementos que han sido correctamente
     * insertados en la Base de Datos local. Se considera elemento insertado a
     * aquellos elementos que han sido descargados e insertados correctamente en
     * la base de datos local, es decir, aquellos que elementos que no se
     * encontraban anteriormente en la base de datos
     *
     * @return El nmero de elementos que han sido correctamente insertados en
     * la peticin.
     */
    public int getInsertados() {
        return insertados;
    }

    /**
     * Funcin que realiza la peticin de los disposistivo.
     *
     * @param <T>
     * @param responseType
     * @return La respuesta de la peticin en el caso de que haya sido correcta.
     * Null en el caso de que se haya producido algn error.
     */
    public <T> T get_Dispositivos(Class<T> responseType) {

        try {
            return webResource.get(responseType);
        } catch (UniformInterfaceException e) {

            if (e.getResponse().toString().endsWith("returned a response status of 204 No Content")) {
                _d.primeERR(label, "Error 204 descargando. Se omite.");
            }

            return null;
        }
    }

    /**
     * Funcin que establece los parmetros para la conexin HTTP
     *
     * @param node Identificador del nodo para el que se va a realiza la
     * peticin HTTP
     */
    public void createWebResource(String node) {

        _d.primeERR("https://cityanalytics.net/restapi/rawdataservice/" + node + "/dispositivos?user="
                + queryParamValues[0] + "&pass=" + queryParamValues[1] + "&start=" + queryParamValues[2] + "&end="
                + queryParamValues[3] + "&inc=true");

        webResource = client.resource("https://cityanalytics.net/restapi/rawdataservice/" + node
                + "/dispositivos?user=" + queryParamValues[0] + "&pass=" + queryParamValues[1] + "&start="
                + queryParamValues[2] + "&end=" + queryParamValues[3] + "&inc=true");

        insertados = 0;
    }

    /**
     * Funcin que procesa mediante JSON el resultado de la peticin HTTP.
     *
     * @param datos La respuesta de la peticin HTTP
     */
    public void procesarDatos(String datos) {
        //Preprocesamos los datos, para darle un nombre al array, cosa que est muy mal que no venga hecha:
        datos = "{\"dispositivos\":" + datos + "}";

        JSONParser parser = new JSONParser();

        try {
            JSONObject obj = (JSONObject) parser.parse(datos);
            JSONArray lista = (JSONArray) obj.get("dispositivos");
            procesados = lista.size();

            int conta = 1;
            int lotes = procesados / MAX_CACHE_SIZE;

            for (int i = 0; i < lista.size(); i++) {

                if (i % MAX_CACHE_SIZE == 0) {
                    conta++;
                }

                String a0 = (String) ((JSONObject) lista.get(i)).get("idDispositivo");
                String a1 = (String) ((JSONObject) lista.get(i)).get("majorDeviceClass");
                String a2 = (String) ((JSONObject) lista.get(i)).get("minorDeviceClass");
                String a3 = (String) ((JSONObject) lista.get(i)).get("serviceClass");
                String a4 = (String) ((JSONObject) lista.get(i)).get("fabricante");

                this.InsertarDatos(
                        "\"" + (String) a0 + "\",\"" + a1 + "\",\"" + a2 + "\",\"" + a3 + "\",\"" + a4 + "\"");

            }
        } catch (Exception e) {
            System.err.println("E>" + e.getMessage());
        }

        syncDB();

    }

    /**
     * Funcin que procesa mediante SPLIT el resultado de la peticin HTTP.
     *
     * @param datos
     * @throws SQLException
     * @deprecated
     * @see ClienteDispositivos.procesarDatos(String datos)
     */
    public void procesarDatosSlit(String datos) throws SQLException {

        String datosAInsertar = "";
        datos = "," + datos;
        String[] result = datos.toString().split("}");
        int conta = 0;
        for (int x = 0; x < result.length - 1; x++) {
            conta++;
            String[] result2 = result[x].split(",");
            for (int y = 1; y < result2.length; y++) {
                String[] result3 = result2[y].split(":");
                //for (int w=1; w<result3.length; w++){
                datosAInsertar += result3[1] + ", ";
                //System.err.println("x,y"+x+", "+y+" "+result3[1] + "|\t|" + datosAInsertar);
                //}
            }

            //this.InsertarDatosSync(datosAInsertar.substring(0, datosAInsertar.lastIndexOf(",")));
            datosAInsertar = "";
        }
        System.out.println("Dispositivos procesados: " + conta);

    }

    /**
     * Funcin que establece la conexin con la base de datos local
     *
     * @param connect Variable de conexin con la base de datos local
     */
    public void setConexion(Conectar connect) {
        this.conexion = connect;
    }

    /**
     * Funcin que borra la tabla en base de datos Local
     * @throws SQLException 
     * @deprecated 
     */
    public void borrarDatosTablaDispositivo() throws SQLException {
        //Statement st = conexion.crearSt();
        //st.execute("Alter table dispositivo disable keys;");
        //st = conexion.crearSt();
        //st.executeUpdate("Delete from dispositivo;");
    }

    public void InsertarDatos(String datos) {
        cache = cache + (cache_size != 0 ? "," : "") + " (" + datos + " ) ";
        cache_size++;

        if (cache_size >= MAX_CACHE_SIZE) {
            syncDB();
        }
    }

    /**
     * Clase encargada de realizar las peticiones SQL a la Base de Datos local de forma paralela.
     */
    public class threadSyncDB extends Thread {

        /**
         * Consulta(s) a realizar en la Base de Datos.
         */
        private String query;

        /**
         * Identificador de la hebra.
         */
        private int id;

        /**
         * Variable de conexin con la Base de Datos Local. 
         */
        private Conectar c;

        /**
         * Variable de control - Indica el nmero de intentos de procesamiento de la peticin.
         */
        int intentos = 0;

        /**
         * Variable de control - Indica si la peticin ha sido procesada ya en la Base de Datos Local.
         */
        boolean procesada = false;

        /**
         * Variable de auditora - Indica el nmero de elementos que han sido insertados en la Base de Datos Local.
         */
        int insertados = 0;

        /**
         * Constructor por defecto de la clase.
         * @param cache Cach de peticiones a realizar en la Base de Datos Local
         * @param i  Identificador de la hebra.
         */
        public threadSyncDB(String cache, int i) {
            query = cache;
            id = i;
        }

        /**
         * Mtodo de ejecucin de la hebra.
         * Procesa las peticiones almacenadas en la cach en la Base de Datos Local.
         */
        @Override
        public void run() {
            do {
                try {
                    this.c = new Conectar();
                    Statement st = c.crearSt();
                    insertados = st.executeUpdate(
                            "INSERT IGNORE INTO dispositivo (idDispositivo, majordeviceclass, minordeviceclass, serviceclass, fabricante) VALUES"
                                    + query + ";");
                    procesada = true;
                    c.cerrar();
                } catch (SQLException ex) {
                    procesada = false;
                    intentos++;
                    if (intentos > MAX_ERRORES_PARA_NOTIFICACION) {
                        _d.primeERR(label, "Error hebra " + this.getId() + " sincronizacin con DB Error "
                                + ex.getErrorCode() + " Se intentar nuevamente (" + intentos + ")");
                    }
                    try {
                        sleep(TIME_SLEEP_IN_ERROR);
                    } catch (InterruptedException ex1) {
                        System.err.println("E>Error durmiendo hebra " + this.getId());
                    }
                } catch (NullPointerException e) {
                    procesada = false;
                    intentos++;
                    if (intentos > 0) {
                        _d.primeERR(label, "Error hebra " + this.getId()
                                + " no se ha podido conectar a la DB. Se intentar nuevamente (" + intentos + ")");
                    }
                    try {
                        sleep(TIME_SLEEP_IN_ERROR);
                    } catch (InterruptedException ex1) {
                        System.err.println("E>Error durmiendo hebra " + this.getId());
                    }
                } catch (Exception ex) {
                    procesada = false;
                    intentos++;
                    if (intentos > 0) {
                        _d.primeERR(label, "Error hebra " + this.getId()
                                + " no se ha podido conectar a la DB. Se intentar nuevamente (" + intentos + ")");
                    }
                    try {
                        sleep(TIME_SLEEP_IN_ERROR);
                    } catch (InterruptedException ex1) {
                        System.err.println("E>Error durmiendo hebra " + this.getId());
                    }

                }
            } while (!procesada);
        }

        /**
         * Finaliza la hebra.
         * @throws Throwable 
         */
        @Override
        protected void finalize() throws Throwable {
            conexion.cerrar();
            super.finalize();
        }
    }

    /**
     * Funcin que sincroniza con la Base de Datos.
     */
    public void syncDB() {
        try {
            l_th.add(new threadSyncDB(cache, l_th.size()));
            l_th.get(l_th.size() - 1).start();

        } catch (Exception ex) {
            System.err.println("E>" + ex.getMessage());

        }
        cache_size = 0;
        cache = "";
    }

    /**
     * Funcin que sincroniza de forma sncrona con la Base de Datos Local.
     * @param datos Peticin a ejecutar en la Base de Datos Local.
     * @throws SQLException Si existe algn error al procesar la peticin en la Base de Datos Local.
     * @deprecated 
     */
    public void InsertarDatosSync(String datos) throws SQLException {
        try {
            String[] comas = datos.split(",");
            if (comas.length < 5) {
                datos = datos + ", \"null\" ";
            }

            Statement st = conexion.crearSt();

            st.executeUpdate(
                    "INSERT INTO dispositivo (idDispositivo, majordeviceclass, minordeviceclass, serviceclass, fabricante) VALUES ("
                            + datos + " )");

            if ((++insertados) % 100 == 0) {
                System.err.print("\n+");
            } else {
                System.err.print("+");
            }
            /*
             idDispositivo: Cadena tras el hash de la MAC Bluetooth de un dispositivo.
             majordeviceclass: Cadena con la caracterstica obtenida de la MAC Bluetooth acerca de la procedencia y capacidades del dispositivo.
             minordeviceclass: Cadena con la caracterstica obtenida de la MAC Bluetooth acerca de la procedencia y capacidades del dispositivo.
             serviceclass: Cadena con la caracterstica obtenida de la MAC Bluetooth acerca de la procedencia y capacidades del dispositivo.
             fabricante: Cadena con el nombre del fabricante del dispositivo Bluetooth detectado.
             */
        } catch (com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException e) {
            return;
        }

    }

    /**
     * Clase encargada de la gestin de las hebras de ejecucin paralela.
     * Se encarga de gestionar que todas las hebras han sido completadas, es decir, que se han procesado todas las peticiones
     * pendiente en la Base de Datos Local.
     */
    public class threadCierre extends Thread {

        /**
         * Lista de hebras de peticiones a la base de datos local.
         */
        private List<threadSyncDB> l = null;

        /**
         * Constructor principal.
         * @param _l Listado de hebras de peticiones a la Base de Datos Local
         */
        public threadCierre(List<ClienteDispositivos.threadSyncDB> _l) {
            this.l = _l;
        }

        /**
         * Metodo principal de la hebra.
         * Espera a la ejecucin y procesado de todas las peticiones pendientes a la Base de Datos Local.
         */
        @Override
        public void run() {
            int insertados = 0;
            _d.primeOUT(label, "Escritura en BD: " + l.size() + " peticiones");
            while (!l.isEmpty()) {
                try {
                    l.get(0).join();
                    insertados = insertados + l.get(0).insertados;
                    l.remove(0);
                } catch (InterruptedException ex) {
                    Logger.getLogger(ClienteDispositivos.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
            _d.primeOUT(label, "Escritura en DB OK.");
            _d.primeOUT(label, "Dispositivos insertados " + insertados + " de " + procesados + " procesados ("
                    + (procesados - insertados) + ")");

        }

        /**
         * Funcin que se encarga de matar a la hebra.
         * @throws Throwable 
         */
        @Override
        protected void finalize() throws Throwable {
            conexion.cerrar();
            l.clear();
            super.finalize();
        }
    }

    /**
     * Funcin que indica que el cliente de sincronicacin tiene que ser cerrado.
     * Gracias a la clase threadCierre se espera que se procesen todas las peticiones pendientes
     * en la Base de Datos Local
     */
    public void close() {
        threadCierre t = new threadCierre(l_th);
        t.start();
        client.destroy();
    }

    private HostnameVerifier getHostnameVerifier() {
        return new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
                return true;
            }
        };
    }

    private MultivaluedMap getQueryOrFormParams(String[] paramNames, String[] paramValues) {
        MultivaluedMap<String, String> qParams = new com.sun.jersey.api.representation.Form();
        for (int i = 0; i < paramNames.length; i++) {
            if (paramValues[i] != null) {
                qParams.add(paramNames[i], paramValues[i]);
            }
        }
        //System.err.println(qParams.toString());
        return qParams;
    }

    private SSLContext getSSLContext() {
        javax.net.ssl.TrustManager x509;
        x509 = new javax.net.ssl.X509TrustManager() {
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                    throws java.security.cert.CertificateException {
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                    throws java.security.cert.CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        SSLContext ctx = null;
        try {
            ctx = SSLContext.getInstance("SSL");
            ctx.init(null, new javax.net.ssl.TrustManager[] { x509 }, null);
        } catch (java.security.GeneralSecurityException ex) {
        }
        return ctx;
    }
}