de.mpg.mpdl.inge.reporting.ReportFHI.java Source code

Java tutorial

Introduction

Here is the source code for de.mpg.mpdl.inge.reporting.ReportFHI.java

Source

/*
 * CDDL HEADER START
 * 
 * The contents of this file are subject to the terms of the Common Development and Distribution
 * License, Version 1.0 only (the "License"). You may not use this file except in compliance with
 * the License.
 * 
 * You can obtain a copy of the license at license/ESCIDOC.LICENSE or
 * http://www.escidoc.org/license. See the License for the specific language governing permissions
 * and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL HEADER in each file and include the License
 * file at license/ESCIDOC.LICENSE. If applicable, add the following below this CDDL HEADER, with
 * the fields enclosed by brackets "[]" replaced with your own identifying information: Portions
 * Copyright [yyyy] [name of copyright owner]
 * 
 * CDDL HEADER END
 */

/*
 * Copyright 2006-2012 Fachinformationszentrum Karlsruhe Gesellschaft fr
 * wissenschaftlich-technische Information mbH and Max-Planck- Gesellschaft zur Frderung der
 * Wissenschaft e.V. All rights reserved. Use is subject to license terms.
 */

package de.mpg.mpdl.inge.reporting;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;
import javax.xml.rpc.ServiceException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import de.mpg.mpdl.inge.util.AdminHelper;
import de.mpg.mpdl.inge.util.PropertyReader;
import de.mpg.mpdl.inge.util.ProxyHelper;
import de.mpg.mpdl.inge.xmltransforming.emailhandling.EmailHandlingBean;
import de.mpg.mpdl.inge.xmltransforming.exceptions.TechnicalException;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRXmlDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRRtfExporter;
import net.sf.jasperreports.engine.query.JRXPathQueryExecuterFactory;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.engine.util.JRXmlUtils;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

/**
 * Monthly report for FHI
 * 
 * @author Vlad Makarenko (initial creation)
 * @author $Author: vmakarenko $ (last modification)
 * @version $Revision:$ $LastChangedDate: $
 * 
 */

public class ReportFHI {

    private final static Logger logger = Logger.getLogger(ReportFHI.class);

    private static TransformerFactory tf = new net.sf.saxon.TransformerFactoryImpl();

    private static EmailHandlingBean emailHandler = new EmailHandlingBean();

    private static final int FLAGS = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;

    private static final Pattern AMPS_ALONE = Pattern.compile("\\&(?!\\w+?;)", FLAGS);

    // number of the last months to be processed

    private static String adminHandler;

    private static Properties rprops;

    public static String USER_NAME;
    public static String USER_PASSWD;
    public static String emailSenderProp;
    public static String emailServernameProp;
    public static String emailWithAuthProp;
    public static String emailAuthUserProp;
    public static String emailAuthPwdProp;

    public ReportFHI() throws IOException, URISyntaxException, ServiceException {
        USER_NAME = PropertyReader.getProperty("framework.admin.username");
        USER_PASSWD = PropertyReader.getProperty("framework.admin.password");
        emailSenderProp = PropertyReader.getProperty("escidoc.pubman_presentation.email.sender");
        emailServernameProp = PropertyReader.getProperty("escidoc.pubman_presentation.email.mailservername");
        emailWithAuthProp = PropertyReader.getProperty("escidoc.pubman_presentation.email.withauthentication");
        emailAuthUserProp = PropertyReader.getProperty("escidoc.pubman_presentation.email.authenticationuser");
        emailAuthPwdProp = PropertyReader.getProperty("escidoc.pubman_presentation.email.authenticationpwd");

        adminHandler = AdminHelper.loginUser(USER_NAME, USER_PASSWD);

        rprops = loadReportProperties();

    }

    // Generate time range query
    // Take all docs from the last months
    public static String[] getStartEndDateOfQuery() {

        SimpleDateFormat dateformatter = new SimpleDateFormat("yyyy-MM-");
        int months;
        try {
            months = new Integer(rprops.getProperty("FHI.report.months.range")).intValue();
        } catch (Exception e) {
            throw new RuntimeException("Cannot read/convert FHI.report.months.range:", e);
        }
        ;

        // from
        Calendar fromMonth = GregorianCalendar.getInstance();
        fromMonth.add(Calendar.MONTH, -months);
        String fromYearMonth = dateformatter.format(fromMonth.getTime());

        // to
        Calendar toMonth = GregorianCalendar.getInstance();
        toMonth.add(Calendar.MONTH, -1);
        String toYearMonth = dateformatter.format(toMonth.getTime());

        return new String[] {
                fromYearMonth + String.format("%02d", fromMonth.getActualMinimum(Calendar.DAY_OF_MONTH)),
                toYearMonth + toMonth.getActualMaximum(Calendar.DAY_OF_MONTH) };
    }

    // Generate query for time range
    private static String getTimeRangeQuery() {
        String[] dd = getStartEndDateOfQuery();
        return "(\"/properties/creation-date\">=\"" + dd[0] + "\"" + " and \"/properties/creation-date\"<=\""
                + dd[1] + "U\")";
    }

    public static String getItemListFromFramework() {

        // Publications of the test context
        // Time range: previous month

        String itemList = null;
        GetMethod method;
        try {
            method = new GetMethod(PropertyReader.getFrameworkUrl() + "/ir/items");
            method.setRequestHeader("Cookie", "escidocCookie=" + adminHandler);
            String query = "operation=searchRetrieve&maximumRecords=1000&query="
                    + URLEncoder.encode(rprops.getProperty("FHI.query"), "UTF-8") + "%20and%20"
                    + URLEncoder.encode(getTimeRangeQuery(), "UTF-8")
                    + URLEncoder.encode(rprops.getProperty("FHI.sort.by"), "UTF-8");
            logger.info("query <" + query + ">");

            method.setQueryString(query);
            logger.info("URI:" + method.getURI());
            HttpClient client = new HttpClient();
            ProxyHelper.executeMethod(client, method);
            logger.info("URI:" + method.getURI() + "\nStatus code:" + method.getStatusCode());
            if (method.getStatusCode() == HttpServletResponse.SC_OK) {
                itemList = method.getResponseBodyAsString();

                // escape all alone &, otherwise filler throws an exception
                itemList = replaceAllTotal(itemList, AMPS_ALONE, "&amp;");

                if (logger.isDebugEnabled())
                    writeToFile("./search-res.xml", itemList.getBytes("UTF-8"));
                logger.info(itemList);

            }
        } catch (Exception e) {
            logger.warn("Exception occured ", e);
            throw new RuntimeException("Cannot get item-list from framework:", e);
        }

        return itemList;
    }

    /**
     * Converts item-list XML to JasperReports DataSource
     * 
     * @return Document
     */
    private static Document getXmlDataSource() {
        // getFilter from framework, FHI specific
        Document document = null;

        StringWriter sw = new StringWriter();

        // get item-list from framework
        Transformer transformer;
        try {
            // resolution of containers, like authors and source names
            transformer = tf
                    .newTemplates(new StreamSource(JRLoader.getLocationInputStream("schemas/make-containers.xsl")))
                    .newTransformer();
            transformer.transform(new StreamSource(new StringReader(getItemListFromFramework())),
                    new StreamResult(sw));

        } catch (Exception e) {
            throw new RuntimeException("Cannot transform item-list XML containers:", e);
        }
        logger.debug("*********************************************************************");
        logger.debug(sw.toString());
        logger.debug("*********************************************************************");

        try {
            document = JRXmlUtils.parse(new InputSource(new StringReader(sw.toString())));
        } catch (Exception e) {
            throw new RuntimeException("Cannot convert item-list XML to JasperReport DataSource:", e);
        }

        return document;

    }

    /**
     * Generate month report files (formats are specified in properties)
     * 
     * @throws JRException
     * @return list of paths to the generated reports
     */
    public static String[] generateReport() throws JRException {

        String[] formats = rprops.getProperty("FHI.report.formats").split(",");

        // GET REPORT FROM JRXMLs
        // compile subreports
        // JasperCompileManager.compileReportToFile("src/main/resources/subreport_creators.jrxml");

        // get main report
        JasperReport jr = null;
        JasperDesign jd;
        jd = JRXmlLoader.load(JRLoader.getLocationInputStream("FHI_Bibilothek_report.jrxml"));
        jr = JasperCompileManager.compileReport(jd);
        if (jr == null) {
            throw new RuntimeException("Compiled report is null: " + "FHI_Bibilothek_report.jrxml");
        }

        Document doc = getXmlDataSource();

        Map<String, Object> params = new HashMap<String, Object>();
        params.put(JRXPathQueryExecuterFactory.PARAMETER_XML_DATA_DOCUMENT, doc);

        // fill report in memory
        JasperPrint jasperPrint;
        jasperPrint = JasperFillManager.fillReport(jr, params, new JRXmlDataSource(doc, jr.getQuery().getText()));

        ArrayList<String> atts = new ArrayList<String>();
        String fn;
        // save in files in formats
        for (String f : formats) {
            if ("pdf".equalsIgnoreCase(f)) {
                JRPdfExporter pdfExp = new JRPdfExporter();
                pdfExp.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
                fn = "FHI_Bibilothek_report.pdf";
                pdfExp.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, fn);
                pdfExp.exportReport();
                atts.add(fn);
            } else if ("rtf".equalsIgnoreCase(f)) {
                JRRtfExporter rtfExp = new JRRtfExporter();
                rtfExp.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
                fn = "FHI_Bibilothek_report.rtf";
                rtfExp.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, fn);
                rtfExp.exportReport();
                atts.add(fn);
            }
        }

        return atts.toArray(new String[atts.size()]);

    }

    /**
     * Send report per email(s)
     * 
     * @param attFileNames - array of paths to report files
     */
    public static void sendReport(String[] attFileNames, boolean testing) {
        // send email with attachments
        String toEmails = (testing ? rprops.getProperty("FHI.recipients.addresses.test")
                : rprops.getProperty("FHI.recipients.addresses"));
        if (toEmails != null && !toEmails.trim().equals("")) {
            String[] timeRange = getStartEndDateOfQuery();
            try {
                emailHandler.sendMail(emailServernameProp, emailWithAuthProp, emailAuthUserProp, emailAuthPwdProp,
                        rprops.getProperty("FHI.sender.address"), toEmails.split(","),
                        rprops.getProperty("FHI.recipients.cc.addresses").split(","),
                        rprops.getProperty("FHI.recipients.bcc.addresses").split(","),
                        rprops.getProperty("FHI.reply.to.addresses").split(","),
                        rprops.getProperty("FHI.subject") + ", von " + timeRange[0] + " bis " + timeRange[1],
                        new String(rprops.getProperty("FHI.body")), attFileNames);
            } catch (TechnicalException e) {
                // TODO Auto-generated catch block
                throw new RuntimeException("Cannot send email:", e);
            }
        }

    }

    /**
     * Generate month report and send it per email
     * 
     * @throws JRException
     */
    public static void generateAndSendReport(boolean testing) throws JRException {
        sendReport(generateReport(), testing);
    }

    /**
     * Load report properties
     * 
     * @return
     */
    public static Properties loadReportProperties() {
        InputStream is;
        Properties props = null;
        try {
            is = JRLoader.getLocationInputStream("reporting.properties");
            props = new Properties();
            props.load(is);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            throw new RuntimeException("Cannot read report props:", e);
        }

        return props;
    }

    /**
     * Joins the elements of the provided array into a single String containing the provided list of
     * elements. Separator will be put between the not null/empty elements
     * 
     * @param arr is the list of the elements.
     * @param delimiter
     * @return joined string
     */
    public static String join(String[] arr, String delimiter) {
        if (arr == null || arr.length == 0)
            return null;
        StringBuffer sb = new StringBuffer();
        if (delimiter == null)
            delimiter = "";
        for (int i = 0, n = arr.length; i < n; i++) {
            if (arr[i] == null || arr[i].trim().equals(""))
                continue;
            sb.append(arr[i]);
            if (i < n - 1)
                sb.append(delimiter);
        }
        String str = sb.toString().replaceAll(Pattern.quote(delimiter) + "$", "");

        return str;
    }

    public static String replaceAllTotal(String what, String expr, String replacement) {
        return Pattern.compile(expr, Pattern.CASE_INSENSITIVE | Pattern.DOTALL).matcher(what)
                .replaceAll(replacement);
    }

    public static String replaceAllTotal(String what, Pattern p, String replacement) {
        return p.matcher(what).replaceAll(replacement);
    }

    protected static void writeToFile(String fileName, byte[] content) throws IOException {
        FileOutputStream fos = new FileOutputStream(fileName);
        fos.write(content);
        fos.close();
    }

    protected static String readFromFile(String fileName) throws IOException {
        int ch;
        StringBuffer buff = new StringBuffer();
        FileInputStream fis = new FileInputStream(fileName);
        while ((ch = fis.read()) != -1)
            buff.append((char) ch);
        fis.close();
        return buff.toString();
    }

    // This is the main application called periodically by a cron job on continuum
    // configured in /usr/local/sbin/reporting
    public static void main(String args[]) throws Exception {
        ReportFHI rep = new ReportFHI();

        ReportFHI.generateAndSendReport(false);
    }

    private static void usage() {
        System.out.println("ReportFHI usage:");
        System.out.println("\tjava ReportFHI");
    }

}