1 /******************************************************************************* 2 * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * Marc R. Hoffmann - initial API and implementation 10 * 11 *******************************************************************************/ 12 package org.jacoco.report; 13 14 import java.io.IOException; 15 import java.io.OutputStream; 16 import java.util.zip.ZipEntry; 17 import java.util.zip.ZipOutputStream; 18 19 /** 20 * Implementation of {@link IMultiReportOutput} that writes files into a 21 * {@link ZipOutputStream}. 22 */ 23 public class ZipMultiReportOutput implements IMultiReportOutput { 24 25 private final ZipOutputStream zip; 26 27 private OutputStream currentEntry; 28 29 /** 30 * Creates a new instance based on the given {@link ZipOutputStream}. 31 * 32 * @param zip 33 * stream to write file entries to 34 */ 35 public ZipMultiReportOutput(final ZipOutputStream zip) { 36 this.zip = zip; 37 } 38 39 /** 40 * Creates a new instance based on the given {@link OutputStream}. 41 * 42 * @param out 43 * stream to write file entries to 44 */ 45 public ZipMultiReportOutput(final OutputStream out) { 46 this(new ZipOutputStream(out)); 47 } 48 49 public OutputStream createFile(final String path) throws IOException { 50 if (currentEntry != null) { 51 currentEntry.close(); 52 } 53 final ZipEntry entry = new ZipEntry(path); 54 zip.putNextEntry(entry); 55 currentEntry = new EntryOutput(); 56 return currentEntry; 57 } 58 59 public void close() throws IOException { 60 zip.close(); 61 } 62 63 private final class EntryOutput extends OutputStream { 64 65 private boolean closed = false; 66 67 @Override 68 public void write(final byte[] b, final int off, final int len) 69 throws IOException { 70 ensureNotClosed(); 71 zip.write(b, off, len); 72 } 73 74 @Override 75 public void write(final byte[] b) throws IOException { 76 ensureNotClosed(); 77 zip.write(b); 78 } 79 80 @Override 81 public void write(final int b) throws IOException { 82 ensureNotClosed(); 83 zip.write(b); 84 } 85 86 @Override 87 public void flush() throws IOException { 88 ensureNotClosed(); 89 zip.flush(); 90 } 91 92 @Override 93 public void close() throws IOException { 94 if (!closed) { 95 closed = true; 96 zip.closeEntry(); 97 } 98 } 99 100 private void ensureNotClosed() throws IOException { 101 if (closed) { 102 throw new IOException("Zip entry already closed."); 103 } 104 } 105 106 } 107 108 } 109