ExecutionDataReader.java
1/*******************************************************************************
2 * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others
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 static java.lang.String.format;
16
17import java.io.EOFException;
18import java.io.IOException;
19import java.io.InputStream;
20
21/**
22 * Deserialization of execution data from binary streams.
23 *
24 * @author Marc R. Hoffmann
25 * @version $Revision: $
26 */
27public class ExecutionDataReader {
28
29 private final CompactDataInput in;
30
31 private IExecutionDataVisitor executionDataVisitor;
32
33 /**
34 * Creates a new reader based on the given input stream input. Depending on
35 * the nature of the underlying stream input should be buffered as most data
36 * is read in single bytes.
37 *
38 * @param input
39 * input stream to read execution data from
40 */
41 public ExecutionDataReader(final InputStream input) {
42 this.in = new CompactDataInput(input);
43 }
44
45 /**
46 * Sets an listener for execution data.
47 *
48 * @param visitor
49 */
50 public void setExecutionDataVisitor(final IExecutionDataVisitor visitor) {
51 this.executionDataVisitor = visitor;
52 }
53
54 /**
55 * Reads all data and reports it to the corresponding visitors.
56 *
57 * @throws IOException
58 * might be thrown by the underlying input stream
59 */
60 public void read() throws IOException {
61 try {
62 while (true) {
63 final byte block = in.readByte();
64 switch (block) {
65 case ExecutionDataWriter.BLOCK_HEADER:
66 readHeader();
67 break;
68 case ExecutionDataWriter.BLOCK_EXECUTIONDATA:
69 readExecutionData();
70 break;
71 default:
72 throw new IOException(format("Unknown block type %x.",
73 Integer.valueOf(block)));
74 }
75 }
76 } catch (final EOFException e) {
77 // expected at the end of the stream
78 }
79 }
80
81 private void readHeader() throws IOException {
82 if (in.readChar() != ExecutionDataWriter.MAGIC_NUMBER) {
83 throw new IOException("Invalid execution data file.");
84 }
85 final char version = in.readChar();
86 if (version != ExecutionDataWriter.FORMAT_VERSION) {
87 throw new IOException(format("Incompatible format version %x.",
88 Integer.valueOf(version)));
89 }
90 }
91
92 private void readExecutionData() throws IOException {
93 final long classid = in.readLong();
94 final String name = in.readUTF();
95 final boolean[] data = new boolean[in.readVarInt()];
96 for (int i = 0; i < data.length; i++) {
97 data[i] = in.readPackedBoolean();
98 }
99 in.finishPackedBoolean();
100 if (executionDataVisitor != null) {
101 executionDataVisitor.visitClassExecution(classid, name, data);
102 }
103 }
104
105}