nl.b3p.kaartenbalie.reporting.ReportThread.java Source code

Java tutorial

Introduction

Here is the source code for nl.b3p.kaartenbalie.reporting.ReportThread.java

Source

/*
 * B3P Kaartenbalie is a OGC WMS/WFS proxy that adds functionality
 * for authentication/authorization, pricing and usage reporting.
 *
 * Copyright 2006, 2007, 2008 B3Partners BV
 * 
 * This file is part of B3P Kaartenbalie.
 * 
 * B3P Kaartenbalie 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.
 * 
 * B3P Kaartenbalie 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 B3P Kaartenbalie.  If not, see <http://www.gnu.org/licenses/>.
 */
package nl.b3p.kaartenbalie.reporting;

import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import nl.b3p.commons.services.FormUtils;
import nl.b3p.kaartenbalie.core.server.Organization;
import nl.b3p.kaartenbalie.core.server.monitoring.Operation;
import nl.b3p.kaartenbalie.core.server.persistence.MyEMFDatabase;
import nl.b3p.kaartenbalie.reporting.castor.HourlyLoad;
import nl.b3p.kaartenbalie.reporting.castor.MonitorReport;
import nl.b3p.kaartenbalie.reporting.castor.Parameters;
import nl.b3p.kaartenbalie.reporting.castor.RequestLoad;
import nl.b3p.kaartenbalie.reporting.castor.RequestSummary;
import nl.b3p.kaartenbalie.reporting.castor.ResponseFrequency;
import nl.b3p.kaartenbalie.reporting.castor.ResponseTime;
import nl.b3p.kaartenbalie.reporting.castor.Service;
import nl.b3p.kaartenbalie.reporting.castor.ServiceProvider;
import nl.b3p.kaartenbalie.reporting.castor.ServiceProviders;
import nl.b3p.kaartenbalie.reporting.castor.TypeSummary;
import nl.b3p.ogc.wfs.v110.WfsServiceProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author Chris Kramer
 */
public class ReportThread extends Thread {

    private static final Log log = LogFactory.getLog(ReportThread.class);
    private static final String[] SERVICES = { "WMS", "WFS" };
    protected Organization organization;
    /* entity manager alleen voor deze class onafhankelijk van thread */
    protected EntityManager em = null;
    private Date startDate;
    private Date endDate;
    private String xsl;
    private String name;
    private String type;

    public void init(Map parameters) throws Exception {
        setParameters(parameters);
        if (type == null || type.length() == 0) {
            type = CastorXmlTransformer.XML;
        }
        if (name == null || name.length() == 0) {
            name = type;
        }
        /* entity manager moet gesloten worden aan einde van de run methode */
        try {
            log.debug("Creating local entity manager ......");
            em = MyEMFDatabase.getEntityManagerFactory().createEntityManager();
        } catch (Throwable e) {
            log.warn("Error creating local entity manager: ", e);
            if (em != null && em.isOpen()) {
                em.close();
            }
            em = null;
        }
    }

    public void run() {

        try {
            EntityTransaction tx = em.getTransaction();

            long processStart = System.currentTimeMillis();

            Report report = new Report();
            tx = em.getTransaction();
            tx.begin();
            try {
                /*
                 * Store all the parameters in the report...
                 */
                report.setOrganization(organization);
                report.setStartDate(startDate);
                report.setEndDate(endDate);
                report.setName(name);
                String mime = (String) CastorXmlTransformer.getContentTypes().get(type);
                report.setReportMime(mime);

                em.persist(report);
                em.flush();
                tx.commit();
            } catch (Exception ex) {
                tx.rollback();
                throw ex;
            }

            try {
                Parameters parameters = new Parameters();
                parameters.setDateEnd(new org.exolab.castor.types.Date(endDate));
                parameters.setDateStart(new org.exolab.castor.types.Date(startDate));
                parameters.setId(Integer.toString(report.getId().intValue()));
                parameters.setOrganization(organization.getName());
                parameters.setTimeStamp(new Date());

                MonitorReport mr = createMonitorReport();

                Long procTime = new Long(System.currentTimeMillis() - processStart);
                parameters.setProcessingTime(procTime.longValue());
                mr.setParameters(parameters);
                report.setProcessingTime(procTime);

                if (type.equalsIgnoreCase(CastorXmlTransformer.HTML)) {
                    CastorXmlTransformer cxt = new CastorXmlTransformer(xsl, MyEMFDatabase.localPath());
                    report.setReportXML(cxt.createHtml(mr));
                } else {
                    CastorXmlTransformer cxt = new CastorXmlTransformer();
                    report.setReportXML(cxt.createXml(mr));
                }
            } catch (Exception e) {
                StringBuffer rerror = new StringBuffer();
                rerror.append("<error>");
                rerror.append(e.getLocalizedMessage());

                StackTraceElement[] ste = e.getStackTrace();
                if (ste.length > 0) {
                    rerror.append(" at ");
                    rerror.append(ste[0].toString());
                }
                rerror.append("</error>");
                report.setReportXML(rerror.toString());
            }

            tx = em.getTransaction();
            tx.begin();
            try {
                em.merge(report);
                em.flush();
                tx.commit();
            } catch (Exception ex) {
                tx.rollback();
                throw ex;
            }
        } catch (Exception e) {
            log.error("", e);
        } finally {
            log.debug("Closing local entity manager ......");
            if (em != null && em.isOpen()) {
                em.close();
            }
            em = null;
        }
    }

    protected MonitorReport createMonitorReport() {
        MonitorReport mr = new MonitorReport();

        for (int i = 0; i < SERVICES.length; i++) {
            Service service = new Service();
            service.setName(SERVICES[i]);

            RequestLoad requestLoad = createRequestLoad(service.getName());
            if (requestLoad != null) {
                service.setRequestLoad(requestLoad);
            }
            RequestSummary requestSummary = createRequestSummary(service.getName());
            if (requestSummary != null) {
                service.setRequestSummary(requestSummary);
            }
            ResponseFrequency responseFrequency = createResponseFrequency(service.getName());
            if (responseFrequency != null) {
                service.setResponseFrequency(responseFrequency);
            }
            ServiceProviders serviceProviders = createServiceProviders(service.getName());
            if (serviceProviders != null) {
                service.setServiceProviders(serviceProviders);
            }

            mr.addService(service);
        }

        return mr;
    }

    protected RequestLoad createRequestLoad(String service) {
        RequestLoad requestLoad = null;

        List resultList = null;
        try {
            resultList = (List) em
                    .createQuery("SELECT count(cr.timestamp), " + "to_char(cr.timestamp, 'DD-MM-YYYY'), "
                            + "to_char(cr.timestamp, 'HH24'), " + "sum(ro.bytesReceivedFromUser), "
                            + "sum(ro.bytesSentToUser), " + "avg(ro.duration), " + "max(ro.duration) "
                            + "FROM ClientRequest AS cr " + "LEFT JOIN cr.requestOperations AS ro "
                            + "WHERE cr.service = :service " + "AND cr.organizationId = :organizationId "
                            + "AND cr.timestamp BETWEEN :startDate AND :endDate " + "AND ro.type = :type "
                            + "GROUP BY to_char(cr.timestamp, 'DD-MM-YYYY'), to_char(cr.timestamp, 'HH24') "
                            + "ORDER BY to_char(cr.timestamp, 'DD-MM-YYYY'), to_char(cr.timestamp, 'HH24') ASC")
                    .setParameter("service", service).setParameter("type", new Integer(Operation.REQUEST))
                    .setParameter("startDate", startDate).setParameter("endDate", endDate)
                    .setParameter("organizationId", organization.getId()).getResultList();
        } catch (NoResultException nre) {
            // nothing to do
        }
        if (resultList != null && resultList.size() > 0) {
            requestLoad = new RequestLoad();
            Iterator it = resultList.iterator();
            while (it.hasNext()) {
                Object[] result = (Object[]) it.next();
                if (result != null && result.length == 7) {

                    HourlyLoad hourlyLoad = new HourlyLoad();

                    Long count = (Long) result[0];
                    hourlyLoad.setCount(count == null ? new Integer(0) : new Integer(count.intValue()));

                    Date datum = FormUtils.StringToDate((String) result[1], null);
                    hourlyLoad.setDate(new org.exolab.castor.types.Date(datum == null ? new Date() : datum));
                    String hour = (String) result[2];
                    hourlyLoad.setHour(new Integer(hour));

                    Long bytesReceived = (Long) result[3];
                    hourlyLoad.setBytesReceivedSum(
                            bytesReceived == null ? new Integer(0) : new Integer(bytesReceived.intValue()));
                    Long bytesSent = (Long) result[4];
                    hourlyLoad.setBytesSentSum(
                            bytesSent == null ? new Integer(0) : new Integer(bytesSent.intValue()));
                    Double durationAvg = (Double) result[5];
                    hourlyLoad.setDurationAvg(
                            durationAvg == null ? new Integer(0) : new Integer(durationAvg.intValue()));
                    Long durationMax = (Long) result[6];
                    hourlyLoad.setDurationMax(
                            durationMax == null ? new Integer(0) : new Integer(durationMax.intValue()));

                    requestLoad.addHourlyLoad(hourlyLoad);
                }
            }
        }
        return requestLoad;
    }

    protected RequestSummary createRequestSummary(String service) {
        RequestSummary requestSummary = null;

        for (int operation = 2; operation <= 5; operation++) {

            Object[] result = null;
            try {
                result = (Object[]) em
                        .createQuery("SELECT count(ro.type), " + "sum(ro.bytesReceivedFromUser), "
                                + "sum(ro.bytesSentToUser), " + "sum(ro.dataSize), " + "avg(ro.duration), "
                                + "max(ro.duration) " + "FROM Operation AS ro "
                                + "WHERE ro.clientRequest.service = :service "
                                + "AND ro.clientRequest.organizationId = :organizationId " + "AND ro.type = :type "
                                + "AND ro.clientRequest.timestamp BETWEEN :startDate AND :endDate "
                                + "GROUP BY ro.type ")
                        .setParameter("service", service).setParameter("type", new Integer(operation))
                        .setParameter("startDate", startDate).setParameter("endDate", endDate)
                        .setParameter("organizationId", organization.getId()).getSingleResult();
            } catch (NoResultException nre) {
                // nothing to do
            }

            if (result != null && result.length == 6) {
                requestSummary = new RequestSummary();
                TypeSummary typeSummary = new TypeSummary();

                Long count = (Long) result[0];
                typeSummary.setCount(count == null ? new Integer(0) : new Integer(count.intValue()));
                Long bytesReceived = (Long) result[1];
                typeSummary.setBytesReceivedSum(
                        bytesReceived == null ? new Integer(0) : new Integer(bytesReceived.intValue()));
                Long bytesSent = (Long) result[2];
                typeSummary.setBytesSentSum(bytesSent == null ? new Integer(0) : new Integer(bytesSent.intValue()));
                Long dataSize = (Long) result[3];
                typeSummary.setDataSizeSum(dataSize == null ? new Integer(0) : new Integer(dataSize.intValue()));
                Double durationAvg = (Double) result[4];
                typeSummary
                        .setDurationAvg(durationAvg == null ? new Integer(0) : new Integer(durationAvg.intValue()));
                Long durationMax = (Long) result[5];
                typeSummary
                        .setDurationMax(durationMax == null ? new Integer(0) : new Integer(durationMax.intValue()));
                typeSummary.setType(Operation.NAME[operation - 1]);

                requestSummary.addTypeSummary(typeSummary);
            }
        }
        return requestSummary;
    }

    protected ResponseFrequency createResponseFrequency(String service) {
        ResponseFrequency responseFrequency = new ResponseFrequency();

        for (int operation = 2; operation <= 6; operation++) {
            int stepSize = 1000;
            int start = 0;
            for (int i = 1; i <= 21; i++) {

                Long msLow = new Long((i - 1) * stepSize + start);
                Long msHigh = new Long(i * stepSize + start);
                Long frequencyHits = null;
                try {
                    if (i <= 20) {
                        frequencyHits = (Long) em
                                .createQuery("SELECT count(*) FROM Operation AS ro "
                                        + "WHERE ro.clientRequest.service = :service "
                                        + "AND ro.clientRequest.organizationId = :organizationId "
                                        + "AND ro.type = :type "
                                        + "AND ro.clientRequest.timestamp BETWEEN :startDate AND :endDate "
                                        + "AND ro.duration BETWEEN :msLow AND :msHigh ")
                                .setParameter("service", service).setParameter("type", new Integer(operation))
                                .setParameter("startDate", startDate).setParameter("endDate", endDate)
                                .setParameter("organizationId", organization.getId()).setParameter("msLow", msLow)
                                .setParameter("msHigh", msHigh).getSingleResult();
                    } else {
                        frequencyHits = (Long) em
                                .createQuery("SELECT count(*) FROM Operation AS ro "
                                        + "WHERE ro.clientRequest.service = :service "
                                        + "AND ro.clientRequest.organizationId = :organizationId "
                                        + "AND ro.type = :type "
                                        + "AND ro.clientRequest.timestamp BETWEEN :startDate AND :endDate "
                                        + "AND ro.duration > :msLow ")
                                .setParameter("service", service).setParameter("type", new Integer(operation))
                                .setParameter("startDate", startDate).setParameter("endDate", endDate)
                                .setParameter("organizationId", organization.getId()).setParameter("msLow", msLow)
                                .getSingleResult();
                        msHigh = new Long(-1);
                    }
                } catch (NoResultException nre) {
                    // nothing to do
                }
                if (frequencyHits != null && frequencyHits.longValue() > 0) {
                    ResponseTime responseTime = new ResponseTime();
                    responseTime.setCount(frequencyHits == null ? 0 : frequencyHits.intValue());
                    responseTime.setDurationHigh(msHigh == null ? new Integer(0) : new Integer(msHigh.intValue()));
                    responseTime.setDurationLow(msLow == null ? new Integer(0) : new Integer(msLow.intValue()));
                    responseTime.setType(Operation.NAME[operation - 1]);

                    responseFrequency.addResponseTime(responseTime);
                }

            }
        }
        if (responseFrequency.getResponseTimeCount() == 0) {
            return null;
        }
        return responseFrequency;
    }

    protected ServiceProviders createServiceProviders(String service) {
        ServiceProviders serviceProviders = null;

        List resultList = null;
        try {
            resultList = (List) em
                    .createQuery("SELECT ro.serviceProviderId, " + "count(ro.serviceProviderId), "
                            + "sum(ro.bytesReceived), " + "sum(ro.bytesSent), " + "avg(ro.requestResponseTime), "
                            + "max(ro.requestResponseTime) " + "FROM ServiceProviderRequest AS ro "
                            + "WHERE ro.clientRequest.service = :service "
                            + "AND ro.clientRequest.organizationId = :organizationId "
                            + "AND ro.clientRequest.timestamp BETWEEN :startDate AND :endDate "
                            + "GROUP BY ro.serviceProviderId ")
                    .setParameter("service", service).setParameter("startDate", startDate)
                    .setParameter("endDate", endDate).setParameter("organizationId", organization.getId())
                    .getResultList();
        } catch (NoResultException nre) {
            // nothing to do
        }
        if (resultList != null && resultList.size() > 0) {
            serviceProviders = new ServiceProviders();
            Iterator it = resultList.iterator();
            while (it.hasNext()) {
                Object[] result = (Object[]) it.next();
                if (result != null && result.length == 6) {
                    ServiceProvider serviceProvider = new ServiceProvider();

                    serviceProvider.setName(getSpName((Integer) result[0], service));
                    Long count = (Long) result[1];
                    serviceProvider.setCount(count == null ? new Integer(0) : new Integer(count.intValue()));
                    Long bytesReceived = (Long) result[2];
                    serviceProvider.setBytesReceivedSum(
                            bytesReceived == null ? new Integer(0) : new Integer(bytesReceived.intValue()));
                    Long bytesSent = (Long) result[3];
                    serviceProvider.setBytesSentSum(
                            bytesSent == null ? new Integer(0) : new Integer(bytesSent.intValue()));
                    Double durationAvg = (Double) result[4];
                    serviceProvider.setDurationAvg(
                            durationAvg == null ? new Integer(0) : new Integer(durationAvg.intValue()));
                    Long durationMax = (Long) result[5];
                    serviceProvider.setDurationMax(
                            durationMax == null ? new Integer(0) : new Integer(durationMax.intValue()));

                    serviceProviders.addServiceProvider(serviceProvider);
                }
            }
        }
        return serviceProviders;
    }

    /**
     * The returned SpName can be a ServiceProvider or a WfsServiceProvider. So
     * if the ServiceProvider is not found the WfsServiceProvider is retrieved.
     * If that one is not provided, onbekend will be returned.
     * 
     * @param id
     * @return
     */
    private String getSpName(Integer id, String service) {
        String spName = "onbekend";
        if ("WFS".equalsIgnoreCase(service)) {
            WfsServiceProvider sp = (WfsServiceProvider) em.find(WfsServiceProvider.class, id);
            if (sp != null) {
                spName = sp.getAbbr();
            }
        } else if ("WMS".equalsIgnoreCase(service)) {//wms
            nl.b3p.wms.capabilities.ServiceProvider sp = (nl.b3p.wms.capabilities.ServiceProvider) em
                    .find(nl.b3p.wms.capabilities.ServiceProvider.class, id);
            if (sp != null) {
                spName = sp.getAbbr();
            }
        }
        return spName;
    }

    public void setParameters(Map parameters) throws Exception {
        if (parameters == null) {
            return;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime((Date) parameters.get("startDate"));
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        startDate = cal.getTime();
        cal.setTime((Date) parameters.get("endDate"));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 99);
        endDate = cal.getTime();
        organization = (Organization) parameters.get("organization");
        xsl = (String) parameters.get("xsl");
        name = (String) parameters.get("name");
        type = (String) parameters.get("type");
    }
}