Java tutorial
/******************************************************************************* * Educational Online Test Delivery System * Copyright (c) 2014 American Institutes for Research * * Distributed under the AIR Open Source License, Version 1.0 * See accompanying file AIR-License-1_0.txt or at * http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf ******************************************************************************/ package org.opentestsystem.authoring.testitembank.service.impl; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import javax.xml.bind.JAXBException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.filefilter.TrueFileFilter; import org.opentestsystem.authoring.testitembank.apipzip.domain.ApipManifest; import org.opentestsystem.authoring.testitembank.domain.ItemHistory; import org.opentestsystem.authoring.testitembank.persistence.GridFsRepository; import org.opentestsystem.authoring.testitembank.service.ZipOutputFileBuilderService; import org.opentestsystem.authoring.testitembank.service.ZipXMLService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import com.google.common.collect.Lists; import com.mongodb.gridfs.GridFSDBFile; public class ApipZipOutputFileBuilderService implements ZipOutputFileBuilderService { private static final Logger LOGGER = LoggerFactory.getLogger(ApipZipOutputFileBuilderService.class); private static final String RELATIVE_MANIFEST_PATH = "/imsmanifest.xml"; @Autowired private GridFsRepository gridFsRepository; @Autowired private ZipXMLService zipXMLService; @Value(value = "${tib.file.pathname:}${tib.file.exportfolder:/tib-exports}") private String localExportDirectory; @Override public File createExportFile(final String exportSetId, final List<ItemHistory> items) throws IOException, JAXBException { final String localDirectoryPath = localExportDirectory + "/" + exportSetId; final List<ApipManifest> manifests = Lists.newArrayList(); // build export file locally for (final ItemHistory item : items) { final GridFSDBFile gridfsFile = gridFsRepository.getById(item.getItemZipGridId()); unzipToLocalDirectory(localDirectoryPath, gridfsFile); // read in this item's manifest file final InputStream manifestFile = new FileInputStream(localDirectoryPath + RELATIVE_MANIFEST_PATH); manifests.add(zipXMLService.extractManifestFromXML(manifestFile)); IOUtils.closeQuietly(manifestFile); } final ApipManifest consolidatedManifest = zipXMLService.consolidateManifests(exportSetId, manifests); FileOutputStream fos = null; try { fos = new FileOutputStream(localDirectoryPath + RELATIVE_MANIFEST_PATH); zipXMLService.writeToManifestToOutputStream(consolidatedManifest, fos); } finally { closeAndFlushQuietly(fos); } return createZipFromLocalDirectory(new File(localDirectoryPath), localDirectoryPath + ".zip"); } private static final void unzipToLocalDirectory(final String parentDir, final GridFSDBFile zipFile) throws IOException { ZipInputStream zipInputStream = null; try { zipInputStream = new ZipInputStream(zipFile.getInputStream()); ZipEntry nextEntry = null; while ((nextEntry = zipInputStream.getNextEntry()) != null) { if (!nextEntry.isDirectory()) { // create local file final File f = new File(parentDir + "/" + nextEntry.getName()); f.getParentFile().mkdirs(); f.createNewFile(); int len = 0; final byte[] buff = new byte[1024]; // write entry to file FileOutputStream fos = null; try { fos = new FileOutputStream(f); while ((len = zipInputStream.read(buff)) > 0) { fos.write(buff, 0, len); } } catch (final FileNotFoundException e) { LOGGER.error("unexcepted FileNotFoundException: ", e); } finally { closeAndFlushQuietly(fos); closeEntryQuiety(zipInputStream); } } } } finally { IOUtils.closeQuietly(zipInputStream); } } private static final File createZipFromLocalDirectory(final File sourceDirectory, final String targetZipName) throws IOException { final Collection<File> filesToZip = FileUtils.listFiles(sourceDirectory, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); FileOutputStream fout = null; ZipOutputStream zout = null; final File targetZip = new File(targetZipName); try { fout = new FileOutputStream(targetZip); zout = new ZipOutputStream(fout); for (final File file : filesToZip) { FileInputStream fin = null; try { fin = new FileInputStream(file); zout.putNextEntry(new ZipEntry(getRelativePath(file, sourceDirectory))); final byte[] buffer = new byte[1024]; int length; while ((length = fin.read(buffer)) > 0) { zout.write(buffer, 0, length); } } finally { IOUtils.closeQuietly(fin); closeEntryQuiety(zout); } } } catch (final FileNotFoundException e) { LOGGER.error("unexcepted FileNotFoundException: ", e); } finally { closeAndFlushQuietly(zout); closeAndFlushQuietly(fout); } return targetZip; } private static final String getRelativePath(final File file, final File parentDir) { final Path filePath = Paths.get(file.getAbsolutePath()); final Path parentDirPath = Paths.get(parentDir.getAbsolutePath()); return parentDirPath.relativize(filePath).toString(); } private static final void closeAndFlushQuietly(final OutputStream os) { try { if (os != null) { os.flush(); os.close(); } } catch (final IOException e) { LOGGER.error("error closing output stream.", e); } } private static final void closeEntryQuiety(final ZipOutputStream zos) { try { if (zos != null) { zos.closeEntry(); } } catch (final IOException e) { LOGGER.error("error closing zip output stream entry.", e); } } private static final void closeEntryQuiety(final ZipInputStream zis) { try { if (zis != null) { zis.closeEntry(); } } catch (final IOException e) { LOGGER.error("error closing zip input stream entry.", e); } } }