com.thejustdo.servlet.CargaMasivaServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.thejustdo.servlet.CargaMasivaServlet.java

Source

/*
 * CargaMasivaServlet.java
 * Copyright (c) Oct 21, 2012, The Just DO! All rights reserved
 * 
 * This software is the confidential and propietary information of The Just DO!.
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered into with 
 * The Just DO!.
 */
package com.thejustdo.servlet;

import com.lowagie.text.DocumentException;
import com.thejustdo.dao.BuyerQueries;
import com.thejustdo.dao.DreamBoxQueries;
import com.thejustdo.dao.ParametersQueries;
import com.thejustdo.model.Beneficiary;
import com.thejustdo.model.Buyer;
import com.thejustdo.model.DreamBox;
import com.thejustdo.resources.Constants;
import com.thejustdo.servlet.security.SecureValidator;
import com.thejustdo.util.Utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.UserTransaction;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.xhtmlrenderer.pdf.ITextRenderer;

/**
 * It's job is mainly a creation in loop for opens.
 *
 * @author Edison F Mendez C [efmcuiti]
 */
public class CargaMasivaServlet extends HttpServlet {

    /**
     * Manages all the persistence operations.
     */
    @Resource
    private UserTransaction utx;
    /**
     * Injects the persistent context.
     */
    @PersistenceUnit
    private EntityManagerFactory emf;
    /**
     * Allows us to print messages on the console.
     */
    private static final Logger log = Logger.getLogger(CargaMasivaServlet.class.getName());

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        log.info(String.format("Welcome to the MULTI-PART!!!"));
        ResourceBundle messages = ResourceBundle.getBundle("com.thejustdo.resources.messages");
        // 0. If no user logged, nothing can be done.
        if (!SecureValidator.checkUserLogged(request, response)) {
            return;
        }

        // 1. Check that we have a file upload request.
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        log.info(String.format("Is multipart?: %s", isMultipart));

        // 2. Getting all the parameters.
        String social_reason = request.getParameter("razon_social");
        String nit = request.getParameter("nit");
        String name = request.getParameter("name");
        String phone = request.getParameter("phone");
        String email = request.getParameter("email");
        String office = (String) request.getSession().getAttribute("actualOffice");
        String open_amount = (String) request.getParameter("valor_tarjeta");
        String open_user = (String) request.getSession().getAttribute("actualUser");

        List<String> errors = new ArrayList<String>();

        // 6. Create a factory for disk-based file items
        DiskFileItemFactory factory = new DiskFileItemFactory();

        // 7. Configure a repository (to ensure a secure temp location is used)
        ServletContext servletContext = this.getServletConfig().getServletContext();
        File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
        log.info(String.format("Temporal repository: %s", repository.getAbsolutePath()));
        factory.setRepository(repository);

        // 8. Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);
        try {
            utx.begin();
            EntityManager em = emf.createEntityManager();
            // Parse the request
            List<FileItem> items = upload.parseRequest(request);
            // 8.0 A set of generated box codes must be maintained.
            Map<String, String> matrix = new HashMap<String, String>();
            // ADDED: Validation 'o file extension.
            String filename = null;

            // Runing through the parameters.
            for (FileItem fi : items) {
                if (fi.isFormField()) {
                    if ("razon_social".equalsIgnoreCase(fi.getFieldName())) {
                        social_reason = fi.getString();
                        continue;
                    }

                    if ("nit".equalsIgnoreCase(fi.getFieldName())) {
                        nit = fi.getString();
                        continue;
                    }

                    if ("name".equalsIgnoreCase(fi.getFieldName())) {
                        name = fi.getString();
                        continue;
                    }

                    if ("phone".equalsIgnoreCase(fi.getFieldName())) {
                        phone = fi.getString();
                        continue;
                    }

                    if ("email".equalsIgnoreCase(fi.getFieldName())) {
                        email = fi.getString();
                        continue;
                    }

                    if ("valor_tarjeta".equalsIgnoreCase(fi.getFieldName())) {
                        open_amount = fi.getString();
                        continue;
                    }
                } else {
                    filename = fi.getName();
                }
            }

            // 3. If we got no file, then a error is generated and re-directed to the exact same page.
            if (!isMultipart) {
                errors.add(messages.getString("error.massive.no_file"));
                log.log(Level.SEVERE, errors.toString());
            }

            // 4. If any of the others paramaeters are missing, then a error must be issued.
            if ((social_reason == null) || ("".equalsIgnoreCase(social_reason.trim()))) {
                errors.add(messages.getString("error.massive.no_social_reason"));
                log.log(Level.SEVERE, errors.toString());
            }

            if ((nit == null) || ("".equalsIgnoreCase(nit.trim()))) {
                errors.add(messages.getString("error.massive.no_nit"));
                log.log(Level.SEVERE, errors.toString());
            }

            if ((name == null) || ("".equalsIgnoreCase(name.trim()))) {
                errors.add(messages.getString("error.massive.no_name"));
                log.log(Level.SEVERE, errors.toString());
            }

            if ((phone == null) || ("".equalsIgnoreCase(phone.trim()))) {
                errors.add(messages.getString("error.massive.no_phone"));
                log.log(Level.SEVERE, errors.toString());
            }

            if ((email == null) || ("".equalsIgnoreCase(email.trim()))) {
                errors.add(messages.getString("error.massive.no_email"));
                log.log(Level.SEVERE, errors.toString());
            }

            // If no filename or incorrect extension.
            if ((filename == null) || (!(filename.endsWith(Constants.MASSIVE_EXT.toLowerCase(Locale.FRENCH)))
                    && !(filename.endsWith(Constants.MASSIVE_EXT.toUpperCase())))) {
                errors.add(messages.getString("error.massive.invalid_ext"));
                log.log(Level.SEVERE, errors.toString());
            }

            // 5. If any errors found, we must break the flow.
            if (errors.size() > 0) {
                request.setAttribute(Constants.ERROR, errors);
                //Redirect the response
                request.getRequestDispatcher("/WEB-INF/jsp/carga_masiva.jsp").forward(request, response);
            }

            for (FileItem fi : items) {
                if (!fi.isFormField()) {
                    // 8.1 Processing the file and building the Beneficiaries.
                    List<Beneficiary> beneficiaries = processFile(fi);
                    log.info(String.format("Beneficiaries built: %d", beneficiaries.size()));

                    // 8.2 If any beneficiaries, then an error is generated.
                    if ((beneficiaries == null) || (beneficiaries.size() < 0)) {
                        errors.add(messages.getString("error.massive.empty_file"));
                        log.log(Level.SEVERE, errors.toString());
                        request.setAttribute(Constants.ERROR, errors);
                        //Redirect the response
                        request.getRequestDispatcher("/WEB-INF/jsp/carga_masiva.jsp").forward(request, response);
                    }

                    // 8.3 Building main parts.
                    Buyer b = buildGeneralBuyer(em, social_reason, nit, name, phone, email);
                    // 8.3.1 The DreamBox has to be re-newed per beneficiary.
                    DreamBox db;
                    for (Beneficiary _b : beneficiaries) {
                        // 8.3.2 Completing each beneficiary.
                        log.info(String.format("Completying the beneficiary: %d", _b.getIdNumber()));
                        db = buildDreamBox(em, b, office, open_amount, open_user);
                        matrix.put(db.getNumber() + "", _b.getGivenNames() + " " + _b.getLastName());
                        _b.setOwner(b);
                        _b.setBox(db);
                        em.merge(_b);
                    }

                }
            }

            // 8.4 Commiting to persistence layer.
            utx.commit();

            // 8.5 Re-directing to the right jsp.
            request.getSession().setAttribute("boxes", matrix);
            request.getSession().setAttribute("boxamount", open_amount + "");
            //Redirect the response
            generateZIP(request, response);
        } catch (Exception ex) {
            errors.add(messages.getString("error.massive.couldnot_process"));
            log.log(Level.SEVERE, errors.toString());
            request.setAttribute(Constants.ERROR, errors);
            request.getRequestDispatcher("/WEB-INF/jsp/carga_masiva.jsp").forward(request, response);
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

    /**
     * Given a stream containing the file to process, it builds all the info
     * related to the beneficiaries for dream boxes
     *
     * @param fi Contains the info related to the file to be processed. <br />
     * <strong>File structure</strong> <ul> <li>0: Identification number.</li>
     * <li>1: Identification type.</li> <li>2: Age.</li> <li>3: Given
     * box.</li> <li>4: Last name.</li> <li>5: Second last name.</li> </ul>
     * @return The list of beneficiaries.
     */
    private List<Beneficiary> processFile(FileItem fi) throws IOException {
        List<Beneficiary> answer = new ArrayList<Beneficiary>();

        // 1. Getting the input stream with the file.
        InputStream stream = fi.getInputStream();
        InputStreamReader isr = new InputStreamReader(stream, "ISO-8859-1");
        BufferedReader reader = new BufferedReader(isr);

        // 2. Parsing line by line.
        String line;
        String parts[];
        Beneficiary b;
        while (reader.ready()) {
            line = reader.readLine();
            // Building the beneficiaries.
            if ((line == null) || ("".equalsIgnoreCase(line.trim()))) {
                continue;
            }

            // 2.1 Spliting parts.
            log.info(String.format("Found line: %s", line));
            parts = line.split(",");
            // 2.2 Building the new elemento of response.
            b = new Beneficiary();
            //b.setIdNumber(Long.parseLong(parts[0]));
            //b.setDocumentType(parts[1]);
            //b.setAge(Integer.parseInt(parts[2]));
            b.setGivenNames(parts[0]);
            b.setLastName(parts[1]);
            //b.setSecondLastName(parts[2]);

            // 2.3 Adding the element to the answer.
            answer.add(b);
        }

        // n. Clossing the stream.
        stream.close();

        return answer;
    }

    /**
     * Builds an object with the owner that at future will be the owner of all
     * the dream boxes created under the broad approach of massive load.
     *
     * @param args Set of properties for the buyer as follows: <ul> <li> 0:
     * Social reason. </li> <li> 1: NIT number. </li> <li> 2: Name. </li> <li>
     * 3: Phone. </li> <li> 4: Email. </li> </ul>
     * @return The built object ready to be persisted and linked.
     */
    private Buyer buildGeneralBuyer(EntityManager em, String... args) {
        // 0. Parsing parameters.
        long idNumber = Long.parseLong(args[1]);
        String buyer_name = args[0];
        String buyer_last_name = args[2];
        String buyer_email = args[4];
        String buyer_cellphone = args[3];

        // 1. If the buyer already exist, we update the info.
        log.info(String.format("Working on buyer with NIT: %d", idNumber));
        Buyer buyer = BuyerQueries.findBuyerById(idNumber, em);
        buyer = (buyer == null) ? new Buyer(idNumber) : buyer;
        buyer.setGivenNames(buyer_name);
        buyer.setLastName(buyer_last_name);
        buyer.setSecondLastName("N/A");
        buyer.setDocumentType("NIT");
        buyer.setPaymentMethod("Cargo a cuenta");
        buyer.setEmail(buyer_email);
        buyer.setCellPhone(buyer_cellphone);
        buyer.setStatus(true);
        em.merge(buyer);
        return buyer;
    }

    /**
     * Builds a new dream box based on the initial info.
     *
     * @param em Manages the persistence layer.
     * @param b Buyer owner of this box.
     * @param args Set of properties for the buyer as follows: <ul> <li> 0:
     * Office. </li> <li> 1: Open amount. </li> <li> 2: Open user. </li> </ul>
     * @return The built dream box.
     */
    private DreamBox buildDreamBox(EntityManager em, Buyer b, String... args) {
        // 0. Parsing parameters.
        String batch = ParametersQueries.getParameterValueByKey(ParametersQueries.BATCH, em);
        long boxCode = DreamBoxQueries.getNextBoxCode(em);
        String office = args[0];
        Double open_amount = Double.parseDouble(args[1]);
        String open_user = args[2];

        // 1 Building the dream box.
        DreamBox box = new DreamBox(boxCode);
        box.setOpenOffice(office);
        box.setOpenAmount(open_amount);
        box.setOpenDate(GregorianCalendar.getInstance().getTime());
        box.setOpenUser(open_user);
        box.setState("activo");
        box.setBoxBatch(batch);
        box.setOwner(b);

        // 2. Sending it to the persistence layer.
        em.merge(box);

        return box;
    }

    /**
     * Builds a ZIP file with all the title-value to be generated with the boxes
     * configuration.
     *
     * @param request Contains all the important data to be used.
     * @param response Allows us to write the content.
     */
    private void generateZIP(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. Getting the content of the plain xhtml file.
        ServletContext sc = this.getServletConfig().getServletContext();
        File tempDir = (File) sc.getAttribute("javax.servlet.context.tempdir");
        File basePath = Utils.preparePDFDirs(tempDir, sc);
        File tmpName = new File(basePath, Constants.PDF_TMP_NAME);
        File d = new File(tempDir, Constants.TMP_TITLES);
        String _xhtml = Utils.getPlainTextFileFromContext(Constants.MASSIVE_LOCATION, sc);
        // 1.1 Cleaning the temporary directory.
        Utils.cleanDirectory(d);

        // log.info(String.format("Prev XHTML content: %s", _xhtml));

        // 2. Getting parameters to configure the PDF content.
        Map<String, String> matrix = (Map<String, String>) request.getSession().getAttribute("boxes");
        String amount = (String) request.getSession().getAttribute("boxamount");

        // 3. Generating the new xhtml per entry.
        String xhtml;
        String name;
        OutputStream os;
        File _new;
        Set<String> keys = matrix.keySet();
        int i = 1;
        try {

            for (String k : keys) {
                name = matrix.get(k);
                xhtml = String.format(_xhtml, name, k, amount);
                Utils.createTMPFile(xhtml, tmpName);
                // 2. Creating the PDF output.
                _new = new File(d, String.format("title%d.pdf", i));
                os = new FileOutputStream(_new);

                // 3. Creating the gross part.
                ITextRenderer renderer = new ITextRenderer();
                renderer.setDocument(tmpName);
                //renderer.setDocumentFromString(xhtml);
                renderer.layout();
                renderer.createPDF(os);
                os.flush();
                os.close();
                i++;
            }

            // log.info(String.format("New XHTML content: %s", xhtml));
            // File f = Utils.createNewFileInsideContext(
            //     Constants.PDF_LOCATION, sc, xhtml, Constants.PDF_TMP);

            // 4. Creating the ZIP file.
            File zip = new File(tempDir, Constants.ZIP_NAME);
            Utils.zipDirectory(d, zip);

            response.setHeader("Content-Type", "application/zip");
            response.setHeader("Content-Disposition", "attachment;filename=\"titulos.zip\"");

            // 3. Writing the file to the output.
            // The csv parameter contains the path to the temp file to be writen.
            FileInputStream fis = new FileInputStream(zip);
            os = response.getOutputStream();

            byte buffer[] = new byte[256];
            int bytesRead;

            while ((bytesRead = fis.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }

            os.flush();
            os.close();
        } catch (DocumentException ex) {
            ex.printStackTrace();
            log.log(Level.SEVERE, null, ex);
        }
    }
}