/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package edu.harvard.iq.dataverse.api; import java.lang.reflect.Type; import java.lang.annotation.Annotation; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import edu.harvard.iq.dataverse.DataFile; import edu.harvard.iq.dataverse.dataaccess.*; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * * @author Leonid Andreev */ @Provider public class BundleDownloadInstanceWriter implements MessageBodyWriter<BundleDownloadInstance> { private static final Logger logger = Logger.getLogger(BundleDownloadInstanceWriter.class.getCanonicalName()); @Override public boolean isWriteable(Class<?> clazz, Type type, Annotation[] annotation, MediaType mediaType) { return clazz == BundleDownloadInstance.class; } @Override public long getSize(BundleDownloadInstance di, Class<?> clazz, Type type, Annotation[] annotation, MediaType mediaType) { return -1; } @Override public void writeTo(BundleDownloadInstance di, Class<?> clazz, Type type, Annotation[] annotation, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream outstream) throws IOException, WebApplicationException { try { if (di.getDownloadInfo() != null && di.getDownloadInfo().getDataFile() != null) { DataAccessRequest daReq = new DataAccessRequest(); DataFile sf = di.getDownloadInfo().getDataFile(); DataFileIO accessObject = DataAccess.createDataAccessObject(sf, daReq); if (accessObject != null) { accessObject.open(); ZipOutputStream zout = new ZipOutputStream(outstream); /* First, the tab file itself: */ String fileName = accessObject.getFileName(); String zipFileName = fileName.replaceAll("\\.tab$", "-bundle.zip"); httpHeaders.add("Content-disposition", "attachment; filename=\"" + zipFileName + "\""); httpHeaders.add("Content-Type", "application/zip; name=\"" + zipFileName + "\""); InputStream instream = accessObject.getInputStream(); ZipEntry e = new ZipEntry(fileName); zout.putNextEntry(e); String varHeaderLine = accessObject.getVarHeader(); if (varHeaderLine != null) { zout.write(varHeaderLine.getBytes()); } byte[] data = new byte[8192]; int i = 0; while ((i = instream.read(data)) > 0) { zout.write(data, 0, i); zout.flush(); } instream.close(); zout.closeEntry(); instream = null; // Now, the original format: String origFormat = null; try { DataFileIO accessObjectOrig = StoredOriginalFile.retreive(accessObject); //.retrieve(sf, (FileAccessIO) accessObject); if (accessObjectOrig != null) { instream = accessObjectOrig.getInputStream(); if (instream != null) { String origFileName = accessObjectOrig.getFileName(); origFormat = accessObject.getMimeType(); e = new ZipEntry(origFileName); zout.putNextEntry(e); i = 0; while ((i = instream.read(data)) > 0) { zout.write(data, 0, i); zout.flush(); } } } } catch (IOException ioex) { // ignore; if for whatever reason the original is not // available, we'll just skip it. logger.warning("failed to retrieve saved original for " + fileName); } finally { if (instream != null) { try {instream.close();} catch (IOException ioex) {} try {zout.closeEntry();} catch (IOException ioex) {} } } instream = null; // And, if the original format was NOT RData, // add an RData version: if (!"application/x-rlang-transport".equals(origFormat)) { try { DataFileIO accessObjectRdata = DataFileConverter.performFormatConversion( sf, (FileAccessIO) accessObject, "RData", "application/x-rlang-transport"); if (accessObjectRdata != null) { instream = accessObjectRdata.getInputStream(); if (instream != null) { String rdataFileName = accessObjectRdata.getFileName(); e = new ZipEntry(rdataFileName); zout.putNextEntry(e); i = 0; while ((i = instream.read(data)) > 0) { zout.write(data, 0, i); zout.flush(); } } } } catch (IOException ioex) { // ignore; if for whatever reason RData conversion is not // available, we'll just skip it. logger.warning("failed to convert tabular data file "+fileName+" to RData."); } finally { if (instream != null) { try{instream.close();}catch(IOException ioex){} try{zout.closeEntry();}catch(IOException ioex){} } } } // And the variable metadata (DDI/XML), if available: if (di.getFileDDIXML() != null) { e = new ZipEntry(fileName.replaceAll("\\.tab$", "-ddi.xml")); zout.putNextEntry(e); zout.write(di.getFileDDIXML().getBytes()); zout.closeEntry(); } // And now the citations: if (di.getFileCitationEndNote() != null) { e = new ZipEntry(fileName.replaceAll("\\.tab$","citation-endnote.xml")); zout.putNextEntry(e); zout.write(di.getFileCitationEndNote().getBytes()); zout.closeEntry(); } if (di.getFileCitationRIS() != null) { e = new ZipEntry(fileName.replaceAll("\\.tab$","citation-ris.ris")); zout.putNextEntry(e); zout.write(di.getFileCitationRIS().getBytes()); zout.closeEntry(); } if (di.getFileCitationBibtex() != null) { e = new ZipEntry(fileName.replaceAll("\\.tab$","citation-bib.bib")); zout.putNextEntry(e); zout.write(di.getFileCitationBibtex().getBytes()); zout.closeEntry(); } zout.close(); return; } } } catch (IOException ioex) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } throw new WebApplicationException(Response.Status.NOT_FOUND); } }