Package eu.planets_project.pp.plato.action

Source Code of eu.planets_project.pp.plato.action.ProjectExportAction

/*******************************************************************************
* Copyright (c) 2006-2010 Vienna University of Technology,
* Department of Software Technology and Interactive Systems
*
* All rights reserved. This program and the accompanying
* materials are made available under the terms of the
* Apache License, Version 2.0 which accompanies
* this distribution, and is available at
* http://www.apache.org/licenses/LICENSE-2.0
*******************************************************************************/

package eu.planets_project.pp.plato.action;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.faces.application.FacesMessage;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.logging.Log;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.DocumentSource;
import org.dom4j.io.XMLWriter;
import org.jboss.annotation.ejb.cache.Cache;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;

import sun.misc.BASE64Encoder;
import eu.planets_project.pp.plato.model.ByteStream;
import eu.planets_project.pp.plato.model.DigitalObject;
import eu.planets_project.pp.plato.model.Plan;
import eu.planets_project.pp.plato.model.PlanProperties;
import eu.planets_project.pp.plato.util.FileUtils;
import eu.planets_project.pp.plato.util.OS;
import eu.planets_project.pp.plato.util.PlatoLogger;
import eu.planets_project.pp.plato.xml.ProjectExporter;

/**
* This class inserts test data into the persistence layer, including import of
* objective trees from case studies.
*
* @author Christoph Becker
*/
@Stateful
@Scope(ScopeType.EVENT)
@Name("projectExport")
@Cache(org.jboss.ejb3.cache.NoPassivationCache.class)
public class ProjectExportAction implements Serializable, IProjectExport {

    private static final long serialVersionUID = 2155152208617526555L;

    private static final Log log = PlatoLogger.getLogger(ProjectExportAction.class);

    @PersistenceContext
    EntityManager em;

    @Remove
    @Destroy
    public void destroy() {

    }

    /**
     * Exports all projects into separate xml files and adds them to a zip archive. 
     * @return null Always returns null, so user stays on same screen after action performed
     */
    public String exportAllProjectsToZip(){
        List<PlanProperties> ppList = em.createQuery("select p from PlanProperties p").getResultList();

        if (!ppList.isEmpty()){
            log.debug("number of plans to export: "+ppList.size());
            String filename = "allprojects.zip";

            String exportPath = OS.getTmpPath() + "export" + System.currentTimeMillis()+"/";
            new File(exportPath).mkdirs();
           
            String binarydataTempPath = exportPath + "binarydata/";
            File binarydataTempDir = new File(binarydataTempPath);
            binarydataTempDir.mkdirs();
           
            try {
                OutputStream out = new BufferedOutputStream(new FileOutputStream(exportPath + filename));
                ZipOutputStream zipOut = new ZipOutputStream(out);
               
                for (PlanProperties pp: ppList) {
                    log.debug("EXPORTING: " + pp.getName());
                    ZipEntry zipAdd = new ZipEntry(String.format("%1$03d", pp.getId())+"-"+ FileUtils.makeFilename(pp.getName())+".xml");
                    zipOut.putNextEntry(zipAdd);
                    // export the complete project, including binary data
                    exportComplete(pp.getId(), zipOut, binarydataTempPath);
                    zipOut.closeEntry();
                }
                zipOut.close();
                out.close();
                new File(exportPath + "finished.info").createNewFile();
               
                FacesMessages.instance().add(FacesMessage.SEVERITY_INFO, "Export was written to: " + exportPath);
                log.info("Export was written to: " + exportPath);
            } catch (IOException e) {
                FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR, "An error occured while generating the export file.");
                log.error("An error occured while generating the export file.", e);
                File errorInfo = new File(exportPath + "error.info");
                try {
                    Writer w = new FileWriter(errorInfo);
                    w.write("An error occured while generating the export file:");
                    w.write(e.getMessage());
                    w.close();
                } catch (IOException e1) {
                    log.error("Could not write error file.");
                }
               
            } finally {
                // remove all binary temp files
                OS.deleteDirectory(binarydataTempDir);
            }
           
        } else {
            FacesMessages.instance().add("No Projects found!");
        }
        return null;
    }
   
    /**
     * Exports the project identified by PlanProperties.Id ppid and writes the document
     * to the given OutputStream - including all binary data.
     * (currently required by {@link #exportAllProjectsToZip()} )
     * - Does NOT clean up temp files written to baseTempPath
     *
     * @param ppid
     * @param out
     * @param baseTempPath used to write temp files for binary data,
     *        must not be used by other exports at the same time
     */
    public void exportComplete(int ppid, OutputStream out, String baseTempPath) {
        BASE64Encoder encoder = new BASE64Encoder();
        ProjectExporter exporter = new ProjectExporter();
        Document doc = exporter.createProjectDoc();

//        int i = 0;
        List<Plan> list = null;
        try {
            list = em.createQuery(
                    "select p from Plan p where p.planProperties.id = "
                            + ppid).getResultList();
        } catch (Exception e1) {
            list = new ArrayList<Plan>();
            FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR, "An error occured while generating the export file.");
            log.error("Could not load planProperties: ", e1);
        }
        try {
            if (list.size() != 1) {
                FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR,
                        "Skipping the export of the plan with properties"+ppid+": Couldnt load.");
            } else {
                //log.debug("adding project "+p.getplanProperties().getName()+" to XML...");
                String tempPath = baseTempPath;
                File tempDir = new File(tempPath);
                tempDir.mkdirs();

                List<Integer> uploadIDs = new ArrayList<Integer>();
                List<Integer> recordIDs = new ArrayList<Integer>();
                try {
                    exporter.addProject(list.get(0), doc, uploadIDs, recordIDs);
                   
                    writeBinaryObjects(recordIDs, uploadIDs, tempPath, encoder);
                    // perform XSLT transformation to get the DATA into the PLANS
                    XMLWriter writer = new XMLWriter(new FileOutputStream("/tmp/testout"+System.currentTimeMillis()+".xml"));
                    writer.write(doc);
                    writer.close();
                    addBinaryData(doc, out, tempPath);
                } catch (IOException e) {
                    FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR, "An error occured while generating the export file.");
                    log.error("Could not open response-outputstream: ", e);
                } catch (TransformerException e) {
                    FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR, "An error occured while generating the export file.");
                    log.error(e);
                }
            }
        } finally {
            /* clean up */
            list.clear();
            list = null;

            em.clear();
            System.gc();
        }

    }

    /**
     *  Performs XSLT transformation to get the DATA into the PLANS
     */
    private void addBinaryData(Document doc, OutputStream out, String aTempDir) throws TransformerException {
        URL xslPath = Thread.currentThread().getContextClassLoader().getResource("data/xslt/bytestreams.xsl");
        InputStream xsl = Thread.currentThread().getContextClassLoader().getResourceAsStream("data/xslt/bytestreams.xsl");
       
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer(new StreamSource(xsl));
        transformer.setParameter("tempDir", aTempDir);

        Source xmlSource = new DocumentSource(doc);
   
        Result outputTarget = new StreamResult(out); //new FileWriter(outFile));
       
        log.debug("starting bytestream transformation ...");
        transformer.transform(xmlSource, outputTarget);
        log.debug("FINISHED bytestream transformation!");
    }
   
    /**
     * Adds all enlisted plans to an XML document, but does NOT write binary data.
     * Instead the Id's of all referenced uploads and sample records are added to the provided lists,
     * this way they can be added later.
     *  
     * @param ppids
     * @param uploadIDs
     * @param recordIDs
     * @return
     */
    public Document exportToXml(List<Integer> ppids, List<Integer> uploadIDs, List<Integer> recordIDs) {
        ProjectExporter exporter = new ProjectExporter();
        Document doc = exporter.createProjectDoc();

        int i = 0;
        for (Integer id: ppids) {
            // load one plan after the other:
            List<Plan> list = em.createQuery(
                    "select p from Plan p where p.planProperties.id = "
                            + id).getResultList();
            if (list.size() != 1) {
                FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR,
                        "Skipping the export of the plan with properties"+id+": Couldnt load.");
            } else {
                //log.debug("adding project "+p.getplanProperties().getName()+" to XML...");
                exporter.addProject(list.get(0), doc, uploadIDs, recordIDs);
            }
            list.clear();
            list = null;
           
            log.info("XMLExport: addString destinationed project ppid="+id);
            i++;
            if ((i%10==0)) {
                em.clear();
                System.gc();
            }
        }
        return doc;
    }

    /**
     * Loads all binary data for the given samplerecord- and upload Ids and dumps it to XML files,  located in tempDir
     *      
     * @param recordIDs
     * @param uploadIDs
     * @param tempDir
     * @param encoder
     * @throws IOException
     */
    private void writeBinaryObjects(List<Integer> recordIDs, List<Integer> uploadIDs, String aTempDir, BASE64Encoder encoder) throws IOException {
        int counter = 0;
        int skip = 0;
        List<Integer> allIDs = new ArrayList<Integer>();
        allIDs.addAll(recordIDs);
        allIDs.addAll(uploadIDs);
        log.info("writing XMLs for bytestreams of digital objects. Size = "+allIDs.size());
        for (Integer id : allIDs) {
            if (counter > 200*1024*1024) { // 200 MB unused stuff lying around
                System.gc();
                counter = 0;
            }
            DigitalObject object = em.find(DigitalObject.class, id);
            if (object.isDataExistent()) {
                counter += object.getData().getSize();
                File f = new File(aTempDir+object.getId()+".xml");
                writeBinaryData(id, object.getData(), f, encoder);
           } else {
               skip++;
           }
           object = null;
        }
        em.clear();
        System.gc();
        log.info("finished writing bytestreams of digital objects. skipped empty objects: "+skip);
    }
   
    /**
     * Dumps binary data to provided file
     * It results in an XML file with a single element: data,
     * @param id
     * @param data
     * @param f
     * @param encoder
     * @throws IOException
     */
    private static void writeBinaryData(int id, ByteStream data, File f, BASE64Encoder encoder) throws IOException {
        Document streamDoc = DocumentHelper.createDocument();
        Element d = streamDoc.addElement("data");
        d.addAttribute("id", ""+id);
        d.setText(encoder.encode(data.getData()));
        XMLWriter writer = new XMLWriter(new BufferedWriter(new FileWriter(f)), ProjectExporter.prettyFormat);
        writer.write(streamDoc);
        writer.flush();
        writer.close();
    }

   
}
TOP

Related Classes of eu.planets_project.pp.plato.action.ProjectExportAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.