ExecutionDataWriter.java revision 993b89bfa176dfb62485f28499e894c162f4c715
1/******************************************************************************* 2 * Copyright (c) 2009, 2010 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 * $Id: $ 12 *******************************************************************************/ 13package org.jacoco.core.data; 14 15import java.io.ByteArrayOutputStream; 16import java.io.IOException; 17import java.io.OutputStream; 18 19/** 20 * Serialization of execution data into binary streams. 21 * 22 * @author Marc R. Hoffmann 23 * @version $Revision: $ 24 */ 25public class ExecutionDataWriter implements ISessionInfoVisitor, 26 IExecutionDataVisitor { 27 28 /** File format version, will be incremented for each incompatible change. */ 29 public static final char FORMAT_VERSION = 0x1005; 30 31 /** Magic number in header for file format identification. */ 32 public static final char MAGIC_NUMBER = 0xC0C0; 33 34 /** Block identifier for file headers. */ 35 public static final byte BLOCK_HEADER = 0x01; 36 37 /** Block identifier for session information. */ 38 public static final byte BLOCK_SESSIONINFO = 0x10; 39 40 /** Block identifier for execution data of a single class. */ 41 public static final byte BLOCK_EXECUTIONDATA = 0x11; 42 43 private final CompactDataOutput out; 44 45 /** 46 * Creates a new writer based on the given output stream. Depending on the 47 * nature of the underlying stream output should be buffered as most data is 48 * written in single bytes. 49 * 50 * @param output 51 * binary stream to write execution data to 52 * @throws IOException 53 */ 54 public ExecutionDataWriter(final OutputStream output) throws IOException { 55 this.out = new CompactDataOutput(output); 56 writeHeader(); 57 } 58 59 /** 60 * Writes an file header to identify the stream and its protocol version. 61 * 62 * @throws IOException 63 */ 64 private void writeHeader() throws IOException { 65 out.writeByte(BLOCK_HEADER); 66 out.writeChar(MAGIC_NUMBER); 67 out.writeChar(FORMAT_VERSION); 68 } 69 70 public void visitSessionInfo(final SessionInfo info) { 71 try { 72 out.writeByte(BLOCK_SESSIONINFO); 73 out.writeUTF(info.getId()); 74 out.writeLong(info.getStartTimeStamp()); 75 out.writeLong(info.getDumpTimeStamp()); 76 } catch (final IOException e) { 77 throw new RuntimeException(e); 78 } 79 } 80 81 public void visitClassExecution(final ExecutionData data) { 82 try { 83 out.writeByte(BLOCK_EXECUTIONDATA); 84 out.writeLong(data.getId()); 85 out.writeUTF(data.getName()); 86 out.writeBooleanArray(data.getData()); 87 } catch (final IOException e) { 88 throw new RuntimeException(e); 89 } 90 } 91 92 /** 93 * Returns the first bytes of a file that represents a valid execution data 94 * file. In any case every execution data file starts with the three bytes 95 * <code>0x01 0xC0 0xC0</code>. 96 * 97 * @return first bytes of a execution data file 98 */ 99 public static final byte[] getFileHeader() { 100 final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 101 try { 102 new ExecutionDataWriter(buffer).writeHeader(); 103 } catch (final IOException e) { 104 // Must not happen with ByteArrayOutputStream 105 throw new AssertionError(e); 106 } 107 return buffer.toByteArray(); 108 } 109 110} 111