001package edu.pdx.cs410J.grader;
002
003import com.google.common.io.ByteStreams;
004import org.slf4j.Logger;
005import org.slf4j.LoggerFactory;
006
007import java.io.*;
008import java.util.Date;
009import java.util.Map;
010import java.util.jar.Attributes;
011import java.util.jar.JarFile;
012import java.util.jar.Manifest;
013import java.util.zip.ZipEntry;
014import java.util.zip.ZipOutputStream;
015
016public class ZipFileMaker {
017  protected static final Logger logger = LoggerFactory.getLogger("edu.pdx.cs410J.grader");
018
019  protected final Map<Attributes.Name, String> manifestEntries;
020  private OutputStream zipStream;
021
022  public ZipFileMaker(File zipFile, Map<Attributes.Name, String> manifestEntries) throws FileNotFoundException {
023    this(new FileOutputStream(zipFile), manifestEntries);
024  }
025
026  public ZipFileMaker(OutputStream zipStream, Map<Attributes.Name, String> manifestEntries) {
027    this.manifestEntries = manifestEntries;
028    this.zipStream = zipStream;
029  }
030
031  protected void makeZipFile(Map<ZipEntry, InputStream> zipFileEntries) throws IOException {
032    ZipOutputStream zos = new ZipOutputStream(zipStream);
033    zos.setMethod(ZipOutputStream.DEFLATED);
034
035    // Create a Manifest for the Zip file containing the name of the
036    // author (userName) and a version that is based on the current
037    // date/time.
038    writeManifestAsEntryInZipFile(zos);
039
040    // Add the source files to the Zip
041    for (Map.Entry<ZipEntry, InputStream> entry : zipFileEntries.entrySet()) {
042      // Add the entry to the ZIP file
043      zos.putNextEntry(entry.getKey());
044
045      ByteStreams.copy(entry.getValue(), zos);
046
047      zos.closeEntry();
048    }
049
050    zos.close();
051  }
052
053  private void writeManifestAsEntryInZipFile(ZipOutputStream zos) throws IOException {
054    Manifest manifest = new Manifest();
055    addEntriesToMainManifest(manifest);
056
057    String entryName = JarFile.MANIFEST_NAME;
058
059    logger.debug("Adding " + entryName + " to zip");
060    ZipEntry entry = new ZipEntry(entryName);
061    entry.setTime(System.currentTimeMillis());
062    entry.setMethod(ZipEntry.DEFLATED);
063
064    zos.putNextEntry(entry);
065    manifest.write(new BufferedOutputStream(zos));
066    zos.closeEntry();
067  }
068
069  private void addEntriesToMainManifest(Manifest manifest) {
070    Attributes attrs = manifest.getMainAttributes();
071
072    // If a manifest doesn't have a version, the other attributes won't get written out.  Lame.
073    attrs.put(Attributes.Name.MANIFEST_VERSION, new Date().toString());
074
075    for (Map.Entry<Attributes.Name, String> entry : this.manifestEntries.entrySet()) {
076      attrs.put(entry.getKey(), entry.getValue());
077    }
078  }
079}