1e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov/******************************************************************************* 2398ee59bebad6835dab57b60157eff16d511709eMarc R. Hoffmann * Copyright (c) 2009, 2015 Mountainminds GmbH & Co. KG and Contributors 3e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * All rights reserved. This program and the accompanying materials 4e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * are made available under the terms of the Eclipse Public License v1.0 5e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * which accompanies this distribution, and is available at 6e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * http://www.eclipse.org/legal/epl-v10.html 7e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 8e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Contributors: 9e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Marc R. Hoffmann - initial API and implementation 10e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 11e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov *******************************************************************************/ 12e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovpackage org.jacoco.core.data; 13e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 14e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.ByteArrayOutputStream; 15e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.IOException; 16e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport java.io.OutputStream; 17e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 18e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovimport org.jacoco.core.internal.data.CompactDataOutput; 19e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 20e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov/** 21e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Serialization of execution data into binary streams. 22e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 23e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikovpublic class ExecutionDataWriter implements ISessionInfoVisitor, 24e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov IExecutionDataVisitor { 25e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 26e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** File format version, will be incremented for each incompatible change. */ 27873114568ee148ea2e15cd036d57bf7b43ba154dMarc R. Hoffmann public static final char FORMAT_VERSION = 0x1007; 28e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 29e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** Magic number in header for file format identification. */ 30e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public static final char MAGIC_NUMBER = 0xC0C0; 31e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 32e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** Block identifier for file headers. */ 33e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public static final byte BLOCK_HEADER = 0x01; 34e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 35e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** Block identifier for session information. */ 36e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public static final byte BLOCK_SESSIONINFO = 0x10; 37e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 38e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** Block identifier for execution data of a single class. */ 39e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public static final byte BLOCK_EXECUTIONDATA = 0x11; 40e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 41e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** Underlying data output */ 42e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov protected final CompactDataOutput out; 43e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 44e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 45e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Creates a new writer based on the given output stream. Depending on the 46e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * nature of the underlying stream output should be buffered as most data is 47e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * written in single bytes. 48e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 49e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @param output 50e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * binary stream to write execution data to 51e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @throws IOException 52e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * if the header can't be written 53e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 54e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public ExecutionDataWriter(final OutputStream output) throws IOException { 55e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov this.out = new CompactDataOutput(output); 56e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov writeHeader(); 57e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 58e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 59e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 60e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Writes an file header to identify the stream and its protocol version. 61e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 62e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @throws IOException 6357f7cf06888f1e34f9ab2e3129c3d433826ecbe1Marc R. Hoffmann * if the header can't be written 64e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 65e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov private void writeHeader() throws IOException { 66e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeByte(BLOCK_HEADER); 67e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeChar(MAGIC_NUMBER); 68e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeChar(FORMAT_VERSION); 69e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 70e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 71e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 72e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Flushes the underlying stream. 73e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 74e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @throws IOException 7557f7cf06888f1e34f9ab2e3129c3d433826ecbe1Marc R. Hoffmann * if the underlying stream can't be flushed 76e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 77e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public void flush() throws IOException { 78e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.flush(); 79e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 80e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 81e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public void visitSessionInfo(final SessionInfo info) { 82e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov try { 83e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeByte(BLOCK_SESSIONINFO); 84e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeUTF(info.getId()); 85e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeLong(info.getStartTimeStamp()); 86e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeLong(info.getDumpTimeStamp()); 87e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } catch (final IOException e) { 88e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov throw new RuntimeException(e); 89e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 90e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 91e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 92e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public void visitClassExecution(final ExecutionData data) { 93e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov try { 94e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeByte(BLOCK_EXECUTIONDATA); 95e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeLong(data.getId()); 96e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov out.writeUTF(data.getName()); 9727e32e433ba0ac1fdec9290d3454d5b369c969ccMarc R. Hoffmann out.writeBooleanArray(data.getProbes()); 98e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } catch (final IOException e) { 99e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov throw new RuntimeException(e); 100e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 101e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 102e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 103e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov /** 104e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * Returns the first bytes of a file that represents a valid execution data 105e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * file. In any case every execution data file starts with the three bytes 106e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * <code>0x01 0xC0 0xC0</code>. 107e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * 108e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov * @return first bytes of a execution data file 109e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov */ 110e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov public static final byte[] getFileHeader() { 111e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 112e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov try { 113e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov new ExecutionDataWriter(buffer); 114e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } catch (final IOException e) { 115e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov // Must not happen with ByteArrayOutputStream 116e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov throw new AssertionError(e); 117e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 118e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov return buffer.toByteArray(); 119e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov } 120e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov 121e69ba4dbb015949c5d84ba7bbb0b53efac28bb23Evgeny Mandrikov} 122