JaCoCo initial drop.
diff --git a/org.jacoco.core/.classpath b/org.jacoco.core/.classpath
new file mode 100644
index 0000000..2d1a430
--- /dev/null
+++ b/org.jacoco.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<classpath>

+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>

+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>

+	<classpathentry kind="src" path="src"/>

+	<classpathentry kind="output" path="bin"/>

+</classpath>

diff --git a/org.jacoco.core/.project b/org.jacoco.core/.project
new file mode 100644
index 0000000..70a5780
--- /dev/null
+++ b/org.jacoco.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<projectDescription>

+	<name>org.jacoco.core</name>

+	<comment></comment>

+	<projects>

+	</projects>

+	<buildSpec>

+		<buildCommand>

+			<name>org.eclipse.jdt.core.javabuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>org.eclipse.pde.ManifestBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+		<buildCommand>

+			<name>org.eclipse.pde.SchemaBuilder</name>

+			<arguments>

+			</arguments>

+		</buildCommand>

+	</buildSpec>

+	<natures>

+		<nature>org.eclipse.pde.PluginNature</nature>

+		<nature>org.eclipse.jdt.core.javanature</nature>

+	</natures>

+</projectDescription>

diff --git a/org.jacoco.core/.settings/org.eclipse.jdt.core.prefs b/org.jacoco.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..a56f637
--- /dev/null
+++ b/org.jacoco.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,78 @@
+#Mon May 18 07:55:32 CEST 2009

+eclipse.preferences.version=1

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5

+org.eclipse.jdt.core.compiler.compliance=1.5

+org.eclipse.jdt.core.compiler.doc.comment.support=enabled

+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error

+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore

+org.eclipse.jdt.core.compiler.problem.deprecation=warning

+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled

+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled

+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning

+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error

+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore

+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled

+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore

+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning

+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning

+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error

+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning

+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning

+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore

+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore

+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public

+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore

+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning

+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=no_tag

+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning

+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning

+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning

+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore

+org.eclipse.jdt.core.compiler.problem.nullReference=warning

+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning

+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore

+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore

+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore

+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning

+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore

+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore

+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled

+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning

+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled

+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore

+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning

+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning

+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore

+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore

+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore

+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.unusedImport=warning

+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning

+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning

+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning

+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=disabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled

+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning

+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

+org.eclipse.jdt.core.compiler.source=1.5

diff --git a/org.jacoco.core/.settings/org.eclipse.jdt.ui.prefs b/org.jacoco.core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..cb85ad6
--- /dev/null
+++ b/org.jacoco.core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,56 @@
+#Fri May 29 18:31:30 CEST 2009

+eclipse.preferences.version=1

+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true

+formatter_profile=_EclEmma

+formatter_settings_version=11

+sp_cleanup.add_default_serial_version_id=true

+sp_cleanup.add_generated_serial_version_id=false

+sp_cleanup.add_missing_annotations=true

+sp_cleanup.add_missing_deprecated_annotations=true

+sp_cleanup.add_missing_methods=false

+sp_cleanup.add_missing_nls_tags=false

+sp_cleanup.add_missing_override_annotations=true

+sp_cleanup.add_serial_version_id=false

+sp_cleanup.always_use_blocks=true

+sp_cleanup.always_use_parentheses_in_expressions=false

+sp_cleanup.always_use_this_for_non_static_field_access=false

+sp_cleanup.always_use_this_for_non_static_method_access=false

+sp_cleanup.convert_to_enhanced_for_loop=false

+sp_cleanup.correct_indentation=false

+sp_cleanup.format_source_code=true

+sp_cleanup.format_source_code_changes_only=false

+sp_cleanup.make_local_variable_final=true

+sp_cleanup.make_parameters_final=true

+sp_cleanup.make_private_fields_final=true

+sp_cleanup.make_type_abstract_if_missing_method=false

+sp_cleanup.make_variable_declarations_final=true

+sp_cleanup.never_use_blocks=false

+sp_cleanup.never_use_parentheses_in_expressions=true

+sp_cleanup.on_save_use_additional_actions=true

+sp_cleanup.organize_imports=true

+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false

+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true

+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true

+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false

+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false

+sp_cleanup.remove_private_constructors=true

+sp_cleanup.remove_trailing_whitespaces=false

+sp_cleanup.remove_trailing_whitespaces_all=true

+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false

+sp_cleanup.remove_unnecessary_casts=true

+sp_cleanup.remove_unnecessary_nls_tags=false

+sp_cleanup.remove_unused_imports=false

+sp_cleanup.remove_unused_local_variables=false

+sp_cleanup.remove_unused_private_fields=true

+sp_cleanup.remove_unused_private_members=false

+sp_cleanup.remove_unused_private_methods=true

+sp_cleanup.remove_unused_private_types=true

+sp_cleanup.sort_members=false

+sp_cleanup.sort_members_all=false

+sp_cleanup.use_blocks=true

+sp_cleanup.use_blocks_only_for_return_and_throw=false

+sp_cleanup.use_parentheses_in_expressions=false

+sp_cleanup.use_this_for_non_static_field_access=false

+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true

+sp_cleanup.use_this_for_non_static_method_access=false

+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true

diff --git a/org.jacoco.core/META-INF/MANIFEST.MF b/org.jacoco.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..51f6999
--- /dev/null
+++ b/org.jacoco.core/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: JaCoCo Core
+Bundle-SymbolicName: org.jacoco.core
+Bundle-Version: 0.1.0.qualifier
+Bundle-Vendor: Mountainminds GmbH & Co. KG
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Import-Package: org.objectweb.asm,
+ org.objectweb.asm.commons,
+ org.objectweb.asm.tree
+Export-Package: org.jacoco.core.data,
+ org.jacoco.core.instr,
+ org.jacoco.core.runtime
diff --git a/org.jacoco.core/about.html b/org.jacoco.core/about.html
new file mode 100644
index 0000000..f5d8b33
--- /dev/null
+++ b/org.jacoco.core/about.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>
+  JaCoCo is a free Java code coverage library implemented by Marc R. Hoffmann.
+  Check <a href="http://www.eclemma.org/devdoc/jacoco.html">http://www.eclemma.org/devdoc/jacoco.html</a>
+  for updates, documentation and support.
+</p>
+
+<h3>License</h3>
+
+<p>
+  The Content in this plug-in is made available by Mountainminds GmbH &amp; Co. KG,
+  Munich. Except indicated below, the Content is provided to you under the terms
+  and conditions of the Eclipse Public License Version 1.0 (&quot;EPL&quot;).
+  A copy of the EPL is available at
+  <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+</p>
+
+<h3>Third-party Licenses</h3>
+    
+<p>
+  This bundle is based on the <a href="http://asm.objectweb.org/">ASM</a>
+  library which is distributed under the following license.  
+</p>
+
+<pre>
+Copyright (c) 2000-2005 INRIA, France Telecom
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holders nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/org.jacoco.core/build.properties b/org.jacoco.core/build.properties
new file mode 100644
index 0000000..a657887
--- /dev/null
+++ b/org.jacoco.core/build.properties
@@ -0,0 +1,5 @@
+source.. = src/

+output.. = bin/

+bin.includes = META-INF/,\

+               .,\

+               about.html

diff --git a/org.jacoco.core/buildhook.xml b/org.jacoco.core/buildhook.xml
new file mode 100644
index 0000000..0cbbe07
--- /dev/null
+++ b/org.jacoco.core/buildhook.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>

+

+<project name="org.jacoco.core.buildhook">

+	

+	<path id="dependencies">

+		<path refid="bundle-org.objectweb.asm"/>

+	</path>

+	

+	<property name="do.compile" value="true"/>

+	<property name="do.package" value="true"/>

+	<property name="do.doc"     value="true"/>

+	

+</project>
\ No newline at end of file
diff --git a/org.jacoco.core/src/org/jacoco/core/data/AbstractCounter.java b/org.jacoco.core/src/org/jacoco/core/data/AbstractCounter.java
new file mode 100644
index 0000000..f6eae89
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/AbstractCounter.java
@@ -0,0 +1,83 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * Base class for {@link ICounter} implementations.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public abstract class AbstractCounter implements ICounter {

+

+	/** total number of items */

+	protected int total;

+

+	/** covered number of items */

+	protected int covered;

+

+	/**

+	 * Creates a instance with the given numbers.

+	 * 

+	 * @param total

+	 *            number of total items

+	 * @param covered

+	 *            number of covered items

+	 */

+	protected AbstractCounter(final int total, final int covered) {

+		this.total = total;

+		this.covered = covered;

+	}

+

+	public int getTotalCount() {

+		return total;

+	}

+

+	public int getCoveredCount() {

+		return covered;

+	}

+

+	public double getRatio() {

+		return (double) covered / total;

+	}

+

+	public int compareTo(final ICounter counter) {

+		return Double.compare(getRatio(), counter.getRatio());

+	}

+

+	@Override

+	public boolean equals(final Object obj) {

+		if (obj instanceof ICounter) {

+			final ICounter that = (ICounter) obj;

+			return this.total == that.getTotalCount()

+					&& this.covered == that.getCoveredCount();

+		} else {

+			return false;

+		}

+	}

+

+	@Override

+	public int hashCode() {

+		return total ^ covered * 17;

+	}

+

+	@Override

+	public String toString() {

+		final StringBuffer b = new StringBuffer("Counter["); //$NON-NLS-1$

+		b.append(getCoveredCount());

+		b.append('/').append(getTotalCount());

+		b.append(']');

+		return b.toString();

+	}

+

+}
\ No newline at end of file
diff --git a/org.jacoco.core/src/org/jacoco/core/data/BlockCoverageData.java b/org.jacoco.core/src/org/jacoco/core/data/BlockCoverageData.java
new file mode 100644
index 0000000..9390ec4
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/BlockCoverageData.java
@@ -0,0 +1,40 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * Coverage data of a single basic block.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class BlockCoverageData extends CoverageDataImpl {

+

+	/**

+	 * Creates a new block data object with the given parameters.

+	 * 

+	 * @param instructionCount

+	 *            number of byte code instructions contained in this block

+	 * @param lineNumbers

+	 *            source lines corresponding to this block

+	 * @param covered

+	 *            <code>true</code>, if this block is covered

+	 */

+	public BlockCoverageData(final int instructionCount,

+			final int[] lineNumbers, final boolean covered) {

+		super(ElementType.BLOCK, true);

+		blockCounter = CounterImpl.getInstance(covered);

+		instructionCounter = CounterImpl.getInstance(instructionCount, covered);

+		lines.increment(lineNumbers, covered);

+	}

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/ClassCoverageData.java b/org.jacoco.core/src/org/jacoco/core/data/ClassCoverageData.java
new file mode 100644
index 0000000..fae0e0f
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/ClassCoverageData.java
@@ -0,0 +1,79 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+import java.util.Collection;

+

+/**

+ * Coverage data of a single class.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class ClassCoverageData extends CoverageDataImpl {

+

+	private final String name;

+

+	private final String bundle;

+

+	/**

+	 * Creates a class coverage data object with the given parameters.

+	 * 

+	 * @param name

+	 *            vm name of the class

+	 * @param bundle

+	 *            optional bundle oder <code>null</code>

+	 * @param methods

+	 *            contained methods

+	 */

+	public ClassCoverageData(final String name, final String bundle,

+			final Collection<ICoverageData> methods) {

+		super(ElementType.CLASS, true);

+		this.name = name;

+		this.bundle = bundle;

+		addAll(methods);

+		// As class is considered as covered when at least one method is

+		// covered:

+		final boolean covered = methodCounter.getCoveredCount() > 0;

+		this.classCounter = CounterImpl.getInstance(covered);

+	}

+

+	/**

+	 * Return the vm name of this class.

+	 * 

+	 * @return vm name

+	 */

+	public String getName() {

+		return name;

+	}

+

+	/**

+	 * Returns the vm name of the package this class belongs to.

+	 * 

+	 * @return vm name of the package

+	 */

+	public String getPackagename() {

+		final int pos = name.lastIndexOf('/');

+		return pos == -1 ? "" : name.substring(0, pos);

+	}

+

+	/**

+	 * Returns the optional bundle identifier for this class.

+	 * 

+	 * @return bundle or <code>null</code>

+	 */

+	public String getBundle() {

+		return bundle;

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/CounterImpl.java b/org.jacoco.core/src/org/jacoco/core/data/CounterImpl.java
new file mode 100644
index 0000000..57ed6a9
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/CounterImpl.java
@@ -0,0 +1,136 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * {@link ICounter} implementations. Implementing a factory pattern allows to

+ * share counter instances.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public abstract class CounterImpl extends AbstractCounter {

+

+	/** Max counter value for which singletons are created */

+	private static final int SINGLETON_LIMIT = 10;

+

+	private static final CounterImpl[][] SINGLETONS = new CounterImpl[SINGLETON_LIMIT + 1][];

+

+	static {

+		for (int i = 0; i <= SINGLETON_LIMIT; i++) {

+			SINGLETONS[i] = new CounterImpl[i + 1];

+			for (int j = 0; j <= i; j++) {

+				SINGLETONS[i][j] = new Fix(i, j);

+			}

+		}

+	}

+

+	/** Constant for Counter with 0/0 values. */

+	public static final CounterImpl COUNTER_0_0 = SINGLETONS[0][0];

+

+	/**

+	 * Mutable version of the counter.

+	 */

+	private static class Var extends CounterImpl {

+		public Var(final int total, final int covered) {

+			super(total, covered);

+		}

+

+		@Override

+		public CounterImpl increment(final ICounter counter) {

+			this.total += counter.getTotalCount();

+			this.covered += counter.getCoveredCount();

+			return this;

+		}

+	}

+

+	/**

+	 * Immutable version of the counter.

+	 */

+	private static class Fix extends CounterImpl {

+		public Fix(final int total, final int covered) {

+			super(total, covered);

+		}

+

+		@Override

+		public CounterImpl increment(final ICounter counter) {

+			return getInstance(this.total + counter.getTotalCount(),

+					this.covered + counter.getCoveredCount());

+		}

+	}

+

+	/**

+	 * Factory method to retrieve a counter with the given number of items.

+	 * 

+	 * @param total

+	 *            total number of items

+	 * @param covered

+	 *            covered number of items

+	 * @return counter instance

+	 */

+	public static CounterImpl getInstance(final int total, final int covered) {

+		if (total <= SINGLETON_LIMIT && covered <= total) {

+			return SINGLETONS[total][covered];

+		} else {

+			return new Var(total, covered);

+		}

+	}

+

+	/**

+	 * Factory method to retrieve a counter with the given number of items.

+	 * 

+	 * @param total

+	 *            total number of items

+	 * @param covered

+	 *            <code>true</code>, if all items are covered

+	 * @return counter instance

+	 */

+	public static CounterImpl getInstance(final int total, final boolean covered) {

+		return getInstance(total, covered ? total : 0);

+	}

+

+	/**

+	 * Factory method to retrieve a counter for a single item.

+	 * 

+	 * @param covered

+	 *            <code>true</code>, if the item is covered

+	 * @return counter instance

+	 */

+	public static CounterImpl getInstance(final boolean covered) {

+		return getInstance(1, covered ? 1 : 0);

+	}

+

+	/**

+	 * Creates a new instance with the given figures.

+	 * 

+	 * @param total

+	 *            total number of items

+	 * @param covered

+	 *            covered number of items

+	 */

+	protected CounterImpl(final int total, final int covered) {

+		super(total, covered);

+	}

+

+	/**

+	 * Returns a counter with values incremented by the numbers of the given

+	 * counter. It is up to the implementation whether this counter instance is

+	 * modified or a new instance is returned.

+	 * 

+	 * @param counter

+	 *            number of additional total and covered items

+	 * @return counter instance with incremented values

+	 */

+	public abstract CounterImpl increment(final ICounter counter);

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/CoverageDataBuilder.java b/org.jacoco.core/src/org/jacoco/core/data/CoverageDataBuilder.java
new file mode 100644
index 0000000..6c23826
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/CoverageDataBuilder.java
@@ -0,0 +1,100 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.HashMap;

+import java.util.Map;

+

+/**

+ * Builder for hierarchical {@link ICoverageData} structures based on execution

+ * and structure information. The builder is constructed for a given

+ * {@link ExecutionDataStore} and then feed with class structure information

+ * through its {@link IStructureOutput} interface.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class CoverageDataBuilder implements IStructureOutput {

+

+	private final ExecutionDataStore executionData;

+

+	private final Map<Long, ClassCoverageData> classes;

+

+	/**

+	 * Create a new builder based on the given execution data.

+	 * 

+	 * @param executionData

+	 *            execution data

+	 */

+	public CoverageDataBuilder(final ExecutionDataStore executionData) {

+		this.executionData = executionData;

+		this.classes = new HashMap<Long, ClassCoverageData>();

+	}

+

+	public IClassStructureOutput classStructure(final long id,

+			final String name, final String bundle) {

+		final boolean[][] covered = executionData.getBlockdata(id);

+		final Collection<ICoverageData> methods = new ArrayList<ICoverageData>();

+		final String[] sourcename = new String[1];

+		return new IClassStructureOutput() {

+			public void sourceFile(final String name) {

+				sourcename[0] = name;

+			}

+

+			public IMethodStructureOutput methodStructure(final int id,

+					final String name, final String desc, final String signature) {

+				final boolean[] c = covered == null ? null : covered[id];

+				return createMethodOutput(name, desc, signature, methods, c);

+			}

+

+			public void end() {

+				final ClassCoverageData classData = new ClassCoverageData(name,

+						bundle, methods);

+				classes.put(Long.valueOf(id), classData);

+				if (sourcename[0] != null) {

+					final SourceFileCoverageData sourceFile = getSourceFile(

+							sourcename[0], classData.getPackagename(), bundle);

+					sourceFile.add(classData);

+				}

+			}

+		};

+	}

+

+	private IMethodStructureOutput createMethodOutput(final String name,

+			final String desc, final String signature,

+			final Collection<ICoverageData> container, final boolean[] covered) {

+		final Collection<ICoverageData> blocks = new ArrayList<ICoverageData>();

+		return new IMethodStructureOutput() {

+			public void block(final int id, final int instructionCount,

+					final int[] lineNumbers) {

+				final boolean c = covered == null ? false : covered[id];

+				blocks.add(new BlockCoverageData(instructionCount, lineNumbers,

+						c));

+			}

+

+			public void end() {

+				container.add(new MethodCoverageData(name, desc, signature,

+						blocks));

+			}

+		};

+	}

+

+	private SourceFileCoverageData getSourceFile(final String filename,

+			final String packagename, final String bundle) {

+		// TODO look for existing file.

+		return new SourceFileCoverageData(filename, packagename, bundle);

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/CoverageDataImpl.java b/org.jacoco.core/src/org/jacoco/core/data/CoverageDataImpl.java
new file mode 100644
index 0000000..05e23d8
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/CoverageDataImpl.java
@@ -0,0 +1,143 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+import java.util.ArrayList;

+import java.util.Collection;

+

+/**

+ * Base implementation for coverage data nodes.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class CoverageDataImpl implements ICoverageData {

+

+	private final ElementType elementType;

+

+	private final Collection<ICoverageData> children;

+

+	/** Counter for blocks. */

+	protected CounterImpl blockCounter;

+

+	/** Counter for instructions. */

+	protected CounterImpl instructionCounter;

+

+	/** Counter for lines, if this element does not have lines. */

+	protected CounterImpl lineCounter;

+

+	/** Line information if this element has lines. */

+	protected final LinesImpl lines;

+

+	/** Counter for methods. */

+	protected CounterImpl methodCounter;

+

+	/** Counter for classes. */

+	protected CounterImpl classCounter;

+

+	/**

+	 * Creates a new coverage data instance of the given element type.

+	 * 

+	 * @param elementType

+	 *            type of the element represented by this instance

+	 * @param hasLines

+	 *            <code>true</code> id this element has source lines

+	 */

+	public CoverageDataImpl(final ElementType elementType,

+			final boolean hasLines) {

+		this.elementType = elementType;

+		children = new ArrayList<ICoverageData>();

+		blockCounter = CounterImpl.COUNTER_0_0;

+		instructionCounter = CounterImpl.COUNTER_0_0;

+		if (hasLines) {

+			lineCounter = null;

+			lines = new LinesImpl();

+		} else {

+			lineCounter = CounterImpl.COUNTER_0_0;

+			lines = null;

+		}

+		methodCounter = CounterImpl.COUNTER_0_0;

+		classCounter = CounterImpl.COUNTER_0_0;

+

+	}

+

+	/**

+	 * Adds the given coverage data instance as a child element. All counters

+	 * are incremented by the values of the given child.

+	 * 

+	 * @param child

+	 *            child element to add

+	 */

+	public void add(final ICoverageData child) {

+		children.add(child);

+		blockCounter = blockCounter.increment(child.getBlockCounter());

+		instructionCounter = instructionCounter.increment(child

+				.getInstructionCounter());

+		if (lineCounter != null) {

+			lineCounter = lineCounter.increment(child.getLineCounter());

+		}

+		if (lines != null) {

+			lines.increment(child.getLines());

+		}

+		methodCounter = methodCounter.increment(child.getMethodCounter());

+		classCounter = classCounter.increment(child.getClassCounter());

+	}

+

+	/**

+	 * Adds the given collection of coverage data instances as child elements.

+	 * All counters are incremented by the values of the given children.

+	 * 

+	 * @param children

+	 *            child elements to add

+	 */

+	public void addAll(final Collection<ICoverageData> children) {

+		for (final ICoverageData child : children) {

+			add(child);

+		}

+	}

+

+	// === ICoverageData ===

+

+	public ElementType getElementType() {

+		return elementType;

+	}

+

+	public Collection<ICoverageData> getChilden() {

+		return children;

+	}

+

+	public ICounter getBlockCounter() {

+		return blockCounter;

+	}

+

+	public ICounter getInstructionCounter() {

+		return instructionCounter;

+	}

+

+	public ICounter getLineCounter() {

+		return lines == null ? lineCounter : lines;

+	}

+

+	public ILines getLines() {

+		return lines;

+	}

+

+	public ICounter getMethodCounter() {

+		return methodCounter;

+	}

+

+	public ICounter getClassCounter() {

+		return classCounter;

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDumper.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDumper.java
new file mode 100644
index 0000000..9ddb5f4
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDumper.java
@@ -0,0 +1,51 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+import java.io.PrintStream;

+

+/**

+ * {@link IExecutionDataOutput} implementation that dumps a textual

+ * representation of coverage data.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class ExecutionDataDumper implements IExecutionDataOutput {

+

+	private final PrintStream out;

+

+	/**

+	 * Dumps coverage data to {@link System#out}.

+	 */

+	public ExecutionDataDumper() {

+		this(System.out);

+	}

+

+	/**

+	 * Dumps coverage data to the given stream.

+	 * 

+	 * @param out

+	 *            dump output

+	 */

+	public ExecutionDataDumper(final PrintStream out) {

+		this.out = out;

+	}

+

+	public void classExecution(final long id, final boolean[][] blockdata) {

+		out.print("class coverage ");

+		out.print(" id=");

+		out.println(Long.toHexString(id));

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
new file mode 100644
index 0000000..6f3faa6
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
@@ -0,0 +1,86 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+import java.util.HashMap;

+import java.util.Map;

+

+/**

+ * In-memory data store for execution data. The data can be added through its

+ * {@link IExecutionDataOutput} interface. If execution data is provided

+ * multiple times for the same class the data is merged, i.e. a block is marked

+ * as executed if it is reported as executed at least once. This allows to merge

+ * coverage date from multiple runs. This class is not thread safe.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class ExecutionDataStore implements IExecutionDataOutput {

+

+	private final Map<Long, boolean[][]> data = new HashMap<Long, boolean[][]>();

+

+	public void classExecution(long classid, boolean[][] blockdata) {

+		boolean[][] current = data.get(classid);

+		if (current != null) {

+			merge(current, blockdata);

+			blockdata = current;

+		}

+		data.put(Long.valueOf(classid), blockdata);

+

+	}

+

+	private static void merge(boolean[][] target, boolean[][] data) {

+		if (target.length != data.length) {

+			throw new IllegalStateException("Incompatible execution data.");

+		}

+		for (int i = 0; i < target.length; i++) {

+			merge(target[i], data[i]);

+		}

+	}

+

+	private static void merge(boolean[] target, boolean[] data) {

+		if (target.length != data.length) {

+			throw new IllegalStateException("Incompatible execution data.");

+		}

+		for (int i = 0; i < target.length; i++) {

+			if (!target[i]) {

+				target[i] = data[i];

+			}

+		}

+	}

+

+	/**

+	 * Returns the coverage data for the class with the given identifier if

+	 * available.

+	 * 

+	 * @param classid

+	 *            class identifier

+	 * @return coverage data or <code>null</code>

+	 */

+	public boolean[][] getBlockdata(long classid) {

+		return data.get(classid);

+	}

+

+	/**

+	 * Writes the content of the store to the given output interface.

+	 * 

+	 * @param output

+	 *            interface to write content to

+	 */

+	public void writeTo(IExecutionDataOutput output) {

+		for (final Map.Entry<Long, boolean[][]> entry : data.entrySet()) {

+			output.classExecution(entry.getKey(), entry.getValue());

+		}

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/IClassStructureOutput.java b/org.jacoco.core/src/org/jacoco/core/data/IClassStructureOutput.java
new file mode 100644
index 0000000..9474924
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/IClassStructureOutput.java
@@ -0,0 +1,51 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * Interface for data output of the internal structure of a single class. This

+ * interface is meant to be implemented by parties that want to retrieve data

+ * from the instrumentation process.

+ */

+public interface IClassStructureOutput {

+

+	/**

+	 * The source file name might be reported through this method call.

+	 * 

+	 * @param name

+	 *            name of the corresponding source file

+	 */

+	public void sourceFile(String name);

+

+	/**

+	 * Called for every instrumented method.

+	 * 

+	 * @param id

+	 *            identifier of this method within the class

+	 * @param name

+	 *            name of the method

+	 * @param desc

+	 *            parameter and return value description

+	 * @param signature

+	 *            generic signature or <code>null</code>

+	 * @return call-back for structure details about the method

+	 */

+	public IMethodStructureOutput methodStructure(int id, String name,

+			String desc, String signature);

+

+	/**

+	 * Called after all information for this class has been emitted.

+	 */

+	public void end();

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/ICounter.java b/org.jacoco.core/src/org/jacoco/core/data/ICounter.java
new file mode 100644
index 0000000..5bca9ca
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/ICounter.java
@@ -0,0 +1,47 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * A counter holds the total and the covered number of particular items like

+ * classes, methods, blocks or instructions. Counters provide canonical

+ * comparison of their covered/total ratios.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: 11 $

+ */

+public interface ICounter extends Comparable<ICounter> {

+

+	/**

+	 * Returns the total count number of instrumented items.

+	 * 

+	 * @return total count of instrumented items

+	 */

+	public int getTotalCount();

+

+	/**

+	 * Returns the total count number of covered items.

+	 * 

+	 * @return total count of covered items

+	 */

+	public int getCoveredCount();

+

+	/**

+	 * Calculates the ratio of covered to total count items. If total count

+	 * items is 0 this method returns NaN.

+	 * 

+	 * @return ratio of covered to total count items

+	 */

+	public double getRatio();

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/ICoverageData.java b/org.jacoco.core/src/org/jacoco/core/data/ICoverageData.java
new file mode 100644
index 0000000..c22413a
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/ICoverageData.java
@@ -0,0 +1,106 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+import java.util.Collection;

+

+/**

+ * Common interface for all data elements storing coverage data.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: 174 $

+ */

+public interface ICoverageData {

+

+	/**

+	 * Type of a element represented by a {@link ICoverageData} instance.

+	 */

+	public enum ElementType {

+

+		/** Basic Block */

+		BLOCK,

+

+		/** Method */

+		METHOD,

+

+		/** Class */

+		CLASS,

+

+		/** Source File */

+		SOURCEFILE,

+

+		/** Java Package */

+		PACKAGE,

+

+		/** Custom compilation */

+		CUSTOM

+

+	}

+

+	/**

+	 * Returns the type of element represented by this node.

+	 * 

+	 * @return type of this node

+	 */

+	public ElementType getElementType();

+

+	/**

+	 * Returns the child elements contained in this node.

+	 * 

+	 * @return child elements

+	 */

+	public Collection<ICoverageData> getChilden();

+

+	/**

+	 * Returns the counter for byte code instructions.

+	 * 

+	 * @return counter for instructions

+	 */

+	public ICounter getInstructionCounter();

+

+	/**

+	 * Returns the counter for blocks.

+	 * 

+	 * @return counter for blocks

+	 */

+	public ICounter getBlockCounter();

+

+	/**

+	 * Returns the counter for lines.

+	 * 

+	 * @return counter for lines

+	 */

+	public ICounter getLineCounter();

+

+	/**

+	 * Returns the line coverage information if this element supports it.

+	 * 

+	 * @return line coverage or <code>null</code>

+	 */

+	public ILines getLines();

+

+	/**

+	 * Returns the counter for methods.

+	 * 

+	 * @return counter for methods

+	 */

+	public ICounter getMethodCounter();

+

+	/**

+	 * Returns the counter for types.

+	 * 

+	 * @return counter for types

+	 */

+	public ICounter getClassCounter();

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataOutput.java b/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataOutput.java
new file mode 100644
index 0000000..5fcd3bb
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataOutput.java
@@ -0,0 +1,39 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * Interface for data output of collected execution data. This interface is

+ * meant to be implemented by parties that want to retrieve data from the

+ * coverage runtime.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public interface IExecutionDataOutput {

+

+	/**

+	 * Provides execution data for the class with the given id. The first

+	 * dimension of the array corresponds to the method id the second to the

+	 * block id as provided with the structure data for this class. A value of

+	 * <code>true</code> indicates that a block has been executed, i.e. its last

+	 * instruction was called.

+	 * 

+	 * @param id

+	 *            id of the instrumented class

+	 * @param blockdata

+	 *            coverage data for the class

+	 */

+	public void classExecution(long id, boolean[][] blockdata);

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/ILines.java b/org.jacoco.core/src/org/jacoco/core/data/ILines.java
new file mode 100644
index 0000000..eb744c1
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/ILines.java
@@ -0,0 +1,66 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * For all elements that are located in a source file and for source files

+ * itself individual line coverage is described by this interface.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: 11 $

+ */

+public interface ILines extends ICounter {

+

+	/** Flag for lines that do not contain code (value is 0x00). */

+	public static final byte NO_CODE = 0x00;

+

+	/** Flag for lines that are not covered (value is 0x01). */

+	public static final byte NOT_COVERED = 0x01;

+

+	/** Flag for lines that are fully covered (value is 0x02). */

+	public static final byte FULLY_COVERED = 0x02;

+

+	/** Flag for lines that are partly covered (value is 0x03). */

+	public static final byte PARTLY_COVERED = NOT_COVERED | FULLY_COVERED;

+

+	/**

+	 * The number of the first line coverage information is available for. If no

+	 * line is yet contained, the method returns -1.

+	 * 

+	 * @return number of the first line or -1

+	 */

+	public int getFirstLine();

+

+	/**

+	 * The number of the last line coverage information is available for. If no

+	 * line is yet contained, the method returns -1.

+	 * 

+	 * @return number of the last line or -1

+	 */

+	public int getLastLine();

+

+	/**

+	 * Returns the coverage status of the given line.

+	 * 

+	 * @see #NO_CODE

+	 * @see #NOT_COVERED

+	 * @see #PARTLY_COVERED

+	 * @see #FULLY_COVERED

+	 * 

+	 * @param line

+	 *            number of the line in question

+	 * @return status of this line

+	 */

+	public byte getStatus(int line);

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/IMethodStructureOutput.java b/org.jacoco.core/src/org/jacoco/core/data/IMethodStructureOutput.java
new file mode 100644
index 0000000..ec2238f
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/IMethodStructureOutput.java
@@ -0,0 +1,42 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * Interface for data output of the internal structure of a single method. This

+ * interface is meant to be implemented by parties that want to retrieve data

+ * from the instrumentation process.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public interface IMethodStructureOutput {

+

+	/**

+	 * Called for every block within the method.

+	 * 

+	 * @param id

+	 *            identifier of the block within the method

+	 * @param instructionCount

+	 *            number of byte code instructions within this block

+	 * @param lineNumbers

+	 *            list of source lines corresponding to this block

+	 */

+	public void block(int id, int instructionCount, int[] lineNumbers);

+

+	/**

+	 * Called after all information for this method has been emitted.

+	 */

+	public void end();

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/IStructureOutput.java b/org.jacoco.core/src/org/jacoco/core/data/IStructureOutput.java
new file mode 100644
index 0000000..afa5353
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/IStructureOutput.java
@@ -0,0 +1,41 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * Interface for data output of the internal class structure. This interface is

+ * meant to be implemented by parties that want to retrieve data from the class

+ * analyzing process.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public interface IStructureOutput {

+

+	/**

+	 * Provides structural information about a class as collected during

+	 * instrumentation.

+	 * 

+	 * @param id

+	 *            unique id for the class

+	 * @param name

+	 *            VM name of the class

+	 * @param bundle

+	 *            optional bundle identifier this class belongs to

+	 * @return call-back for structure details about the class

+	 * 

+	 */

+	public IClassStructureOutput classStructure(long id, String name,

+			String bundle);

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/LinesImpl.java b/org.jacoco.core/src/org/jacoco/core/data/LinesImpl.java
new file mode 100644
index 0000000..97553b3
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/LinesImpl.java
@@ -0,0 +1,135 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * {@link ILines} implementation.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class LinesImpl extends AbstractCounter implements ILines {

+

+	/** status for each line */

+	private byte[] status;

+

+	/** first line number in lines */

+	private int offset;

+

+	/**

+	 * Creates an empty line counter.

+	 */

+	public LinesImpl() {

+		super(0, 0);

+		status = null;

+		offset = -1;

+	}

+

+	/**

+	 * Created a line counter with the given lines

+	 * 

+	 * @param lines

+	 *            line numbers to add

+	 * @param covered

+	 *            <code>true</code> if all lines are covered

+	 * 

+	 */

+	public LinesImpl(final int[] lines, final boolean covered) {

+		this();

+		increment(lines, covered);

+	}

+

+	private void ensureCapacity(final int first, final int last) {

+		if (status == null) {

+			offset = first;

+			status = new byte[last - first + 1];

+		} else {

+			final int newFirst = Math.min(getFirstLine(), first);

+			final int newLast = Math.max(getLastLine(), last);

+			final int newLength = newLast - newFirst + 1;

+			if (newLength > status.length) {

+				final byte[] newStatus = new byte[newLength];

+				System.arraycopy(status, 0, newStatus, offset - newFirst,

+						status.length);

+				offset = newFirst;

+				status = newStatus;

+			}

+		}

+	}

+

+	/**

+	 * Adds the given lines as fully covered or not covered.

+	 * 

+	 * @param lines

+	 *            line numbers to add

+	 * @param covered

+	 *            <code>true</code> if all lines are covered

+	 * 

+	 */

+	public void increment(final int[] lines, final boolean covered) {

+		if (lines.length > 0) {

+			ensureCapacity(lines[0], lines[lines.length - 1]);

+			final byte newStatus = covered ? FULLY_COVERED : NOT_COVERED;

+			for (final int line : lines) {

+				incrementLine(line, newStatus);

+			}

+		}

+	}

+

+	/**

+	 * Adds the lines of the given line counter. The states are updated

+	 * accordingly.

+	 * 

+	 * @param counter

+	 *            line counter to add

+	 */

+	public void increment(final ILines counter) {

+		if (counter.getTotalCount() == 0) {

+			return;

+		}

+		ensureCapacity(counter.getFirstLine(), counter.getLastLine());

+		for (int line = counter.getFirstLine(); line <= counter.getLastLine(); line++) {

+			incrementLine(line, counter.getStatus(line));

+		}

+	}

+

+	private void incrementLine(final int line, final byte newStatus) {

+		final byte oldStatus = status[line - offset];

+		status[line - offset] = (byte) (oldStatus | newStatus);

+		if (oldStatus == NO_CODE && newStatus != NO_CODE) {

+			total++;

+		}

+		if ((oldStatus == NO_CODE || oldStatus == NOT_COVERED)

+				&& (newStatus == PARTLY_COVERED || newStatus == FULLY_COVERED)) {

+			covered++;

+		}

+	}

+

+	// === ILineCounter ===

+

+	public int getFirstLine() {

+		return offset;

+	}

+

+	public int getLastLine() {

+		return status == null ? -1 : (offset + status.length - 1);

+	}

+

+	public byte getStatus(final int line) {

+		if (status == null || line < getFirstLine() || line > getLastLine()) {

+			return NO_CODE;

+		}

+		return status[line - offset];

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/MethodCoverageData.java b/org.jacoco.core/src/org/jacoco/core/data/MethodCoverageData.java
new file mode 100644
index 0000000..49ab629
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/MethodCoverageData.java
@@ -0,0 +1,80 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+import java.util.Collection;

+

+/**

+ * Coverage data of a single method.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class MethodCoverageData extends CoverageDataImpl {

+

+	private final String name;

+	private final String desc;

+	private final String signature;

+

+	/**

+	 * Creates a method coverage data object with the given parameters.

+	 * 

+	 * @param name

+	 *            name of the method

+	 * @param desc

+	 *            parameter description

+	 * @param signature

+	 *            generic signature or <code>null</code>

+	 * @param blocks

+	 *            contained blocks

+	 */

+	public MethodCoverageData(final String name, final String desc,

+			final String signature, final Collection<ICoverageData> blocks) {

+		super(ElementType.METHOD, true);

+		this.name = name;

+		this.desc = desc;

+		this.signature = signature;

+		addAll(blocks);

+		// A method is considered as covered when at least one block is covered:

+		final boolean covered = getBlockCounter().getCoveredCount() > 0;

+		methodCounter = CounterImpl.getInstance(covered);

+	}

+

+	/**

+	 * Return the name of the method.

+	 * 

+	 * @return name of the method

+	 */

+	public String getName() {

+		return name;

+	}

+

+	/**

+	 * Returns the parameter description of the method.

+	 * 

+	 * @return parameter description

+	 */

+	public String getDesc() {

+		return desc;

+	}

+

+	/**

+	 * Returns the generic signature of the method if defined.

+	 * 

+	 * @return generic signature or <code>null</code>

+	 */

+	public String getSignature() {

+		return signature;

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/SourceFileCoverageData.java b/org.jacoco.core/src/org/jacoco/core/data/SourceFileCoverageData.java
new file mode 100644
index 0000000..4c1ab77
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/SourceFileCoverageData.java
@@ -0,0 +1,75 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.data;

+

+/**

+ * Coverage data of a single source file. As source file contains one or more

+ * classes.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class SourceFileCoverageData extends CoverageDataImpl {

+

+	private final String bundle;

+

+	private final String packagename;

+

+	private final String filename;

+

+	/**

+	 * Creates a source file data object with the given parameters.

+	 * 

+	 * @param filename

+	 *            name of the source file

+	 * @param packagename

+	 *            vm name of the package the source file belongs to

+	 * @param bundle

+	 *            optional bundle name

+	 */

+	public SourceFileCoverageData(final String filename,

+			final String packagename, final String bundle) {

+		super(ElementType.SOURCEFILE, true);

+		this.bundle = bundle;

+		this.packagename = packagename;

+		this.filename = filename;

+	}

+

+	/**

+	 * Returns the source file name.

+	 * 

+	 * @return source file name

+	 */

+	public String getFilename() {

+		return filename;

+	}

+

+	/**

+	 * Returns the vm name of the package the source file belongs to.

+	 * 

+	 * @return package name

+	 */

+	public String getPackagename() {

+		return packagename;

+	}

+

+	/**

+	 * Returns an optional bundle identifier.

+	 * 

+	 * @return bundle identifier or <code>null</code>

+	 */

+	public String getBundle() {

+		return bundle;

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/data/package.html b/org.jacoco.core/src/org/jacoco/core/data/package.html
new file mode 100644
index 0000000..9212000
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/package.html
@@ -0,0 +1,9 @@
+<html>

+<body>

+

+<p>

+  This package contains the classes to calculate and store coverage data.

+</p>

+

+</body>

+</html>

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/Analyzer.java b/org.jacoco.core/src/org/jacoco/core/instr/Analyzer.java
new file mode 100644
index 0000000..ded601c
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/Analyzer.java
@@ -0,0 +1,213 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.IOException;

+import java.io.InputStream;

+import java.util.StringTokenizer;

+import java.util.zip.ZipEntry;

+import java.util.zip.ZipInputStream;

+

+import org.jacoco.core.data.IClassStructureOutput;

+import org.jacoco.core.data.IStructureOutput;

+import org.objectweb.asm.ClassReader;

+import org.objectweb.asm.ClassVisitor;

+import org.objectweb.asm.Opcodes;

+

+/**

+ * Several APIs to analyze class structures.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class Analyzer {

+

+	private final IStructureOutput structureOutput;

+

+	/**

+	 * Creates a new analyzer reporting to the given output.

+	 * 

+	 * @param structureOutput

+	 *            the output instance that will receive all structure data

+	 */

+	public Analyzer(IStructureOutput structureOutput) {

+		this.structureOutput = structureOutput;

+	}

+

+	/**

+	 * Creates an ASM class visitor for analysis.

+	 * 

+	 * @param classid

+	 *            id of the class calculated with {@link CRC64}

+	 * @param classname

+	 *            VM name of the class

+	 * @param bundle

+	 *            optional bundle this class belongs to

+	 * @return ASM visitor to write class definition to

+	 */

+	public ClassVisitor createAnalyzingVisitor(long classid, String classname,

+			String bundle) {

+		final IClassStructureOutput classStructure = structureOutput

+				.classStructure(classid, classname, bundle);

+		return new ClassAnalyzer(classStructure);

+	}

+

+	/**

+	 * Analyzes the class given as a ASM reader.

+	 * 

+	 * @param reader

+	 *            reader with class definitions

+	 * @param bundle

+	 *            optional bundle this class belongs to

+	 */

+	public void analyze(ClassReader reader, String bundle) {

+		if ((reader.getAccess() & Opcodes.ACC_INTERFACE) != 0) {

+			return;

+		}

+

+		final ClassVisitor visitor = createAnalyzingVisitor(CRC64

+				.checksum(reader.b), reader.getClassName(), bundle);

+		reader.accept(visitor, 0);

+	}

+

+	/**

+	 * Analyzes the class definition from a given in-memory buffer.

+	 * 

+	 * @param buffer

+	 *            class definitions

+	 * @param bundle

+	 *            optional bundle this class belongs to

+	 */

+	public void analyze(byte[] buffer, String bundle) {

+		analyze(new ClassReader(buffer), bundle);

+	}

+

+	/**

+	 * Analyzes the class definition from a given input stream.

+	 * 

+	 * @param input

+	 *            stream to read class definition from

+	 * @param bundle

+	 *            optional bundle this class belongs to

+	 * @throws IOException

+	 */

+	public void analyze(InputStream input, String bundle) throws IOException {

+		analyze(new ClassReader(input), bundle);

+	}

+

+	/**

+	 * Analyzes the class definition contained in a given file.

+	 * 

+	 * @param file

+	 *            class file

+	 * @param bundle

+	 *            optional bundle this class belongs to

+	 * @throws IOException

+	 */

+	public void analyze(File file, String bundle) throws IOException {

+		final InputStream in = new FileInputStream(file);

+		analyze(new ClassReader(in), bundle);

+		in.close();

+	}

+

+	/**

+	 * Analyzes all class files contained in the given directory and its

+	 * children.

+	 * 

+	 * @param directory

+	 *            folder to look for class files

+	 * @param bundle

+	 *            optional bundle all the classes belong to

+	 * @throws IOException

+	 */

+	public void analyzeAll(File directory, String bundle) throws IOException {

+		for (final File f : directory.listFiles()) {

+			if (f.isDirectory()) {

+				analyzeAll(directory, bundle);

+				continue;

+			}

+			if (f.getName().endsWith(".class")) {

+				analyze(f, bundle);

+			}

+		}

+	}

+

+	/**

+	 * Analyzes all class files contained in a JAR file.

+	 * 

+	 * @param input

+	 *            stream to read the JAR file from

+	 * @param bundle

+	 *            optional bundle all the classes belong to

+	 * @throws IOException

+	 */

+	public void analyzeJAR(InputStream input, String bundle) throws IOException {

+		final ZipInputStream zip = new ZipInputStream(input);

+		while (true) {

+			final ZipEntry entry = zip.getNextEntry();

+			if (entry == null) {

+				break;

+			}

+			if (entry.getName().endsWith(".class")) {

+				analyze(zip, bundle);

+			}

+		}

+	}

+

+	/**

+	 * Analyzes all class files contained in a JAR file.

+	 * 

+	 * @param jarfile

+	 *            JAR file

+	 * @param bundle

+	 *            optional bundle all the classes belong to

+	 * @throws IOException

+	 */

+	public void analyzeJAR(File jarfile, String bundle) throws IOException {

+		final InputStream in = new FileInputStream(jarfile);

+		analyzeJAR(in, bundle);

+		in.close();

+	}

+

+	/**

+	 * Analyzes all class from the given class path.

+	 * 

+	 * @param path

+	 *            path definition

+	 * @param basedir

+	 *            optional base directory, if <code>null</code> the current

+	 *            working directory is used as the base for relative path

+	 *            entries

+	 * @param bundle

+	 *            optional bundle all the classes belong to

+	 * @throws IOException

+	 */

+	public void analyzePath(String path, File basedir, String bundle)

+			throws IOException {

+		final StringTokenizer tokenizer = new StringTokenizer(path,

+				File.pathSeparator);

+		while (tokenizer.hasMoreTokens()) {

+			final File entry = new File(basedir, tokenizer.nextToken());

+			if (entry.isDirectory()) {

+				analyzeAll(entry, bundle);

+				continue;

+			}

+			if (entry.isFile() && entry.getName().endsWith(".jar")) {

+				analyzeJAR(entry, bundle);

+			}

+		}

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/BlockMethodAdapter.java b/org.jacoco.core/src/org/jacoco/core/instr/BlockMethodAdapter.java
new file mode 100644
index 0000000..1231e6f
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/BlockMethodAdapter.java
@@ -0,0 +1,247 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import java.util.HashSet;

+import java.util.Set;

+

+import org.objectweb.asm.Label;

+import org.objectweb.asm.MethodAdapter;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.tree.MethodNode;

+

+/**

+ * A method visitor that determines block boundaries and reports them to the

+ * wrapped {@link IBlockMethodVisitor}. The implementation first buffers the

+ * content of the method to extract all control flow target labels. At the end

+ * of the method it flushes the content to the {@link IBlockMethodVisitor}.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public final class BlockMethodAdapter extends MethodNode {

+

+	private final IBlockMethodVisitor blockVisitor;

+

+	private final Set<Label> targetLabels;

+

+	private int blockCount;

+

+	/**

+	 * Create a new adapter for the given block visitor.

+	 * 

+	 * @param blockVisitor

+	 *            visitor to report block boundaries to

+	 * @param access

+	 *            the method's access flags

+	 * @param name

+	 *            the method's name.

+	 * @param desc

+	 *            the method's descriptor

+	 * @param signature

+	 *            the method's signature. May be <tt>null</tt>.

+	 * @param exceptions

+	 *            the internal names of the method's exception classes. May be

+	 *            <tt>null</tt>.

+	 */

+	public BlockMethodAdapter(IBlockMethodVisitor blockVisitor,

+			final int access, final String name, final String desc,

+			final String signature, final String[] exceptions) {

+		super(access, name, desc, signature, exceptions);

+		this.blockVisitor = blockVisitor;

+		this.targetLabels = new HashSet<Label>();

+		this.blockCount = 0;

+	}

+

+	/**

+	 * Returns the number of blocks found in the method. A valid return value

+	 * can only be expected after {@link #visitEnd()} has been called.

+	 * 

+	 * @return number of block in the method

+	 */

+	public int getBlockCount() {

+		return blockCount;

+	}

+

+	// === MethodVisitor ===

+

+	@Override

+	public void visitJumpInsn(int opcode, Label label) {

+		targetLabels.add(label);

+		super.visitJumpInsn(opcode, label);

+	}

+

+	@Override

+	public void visitTableSwitchInsn(int min, int max, Label dflt,

+			Label[] labels) {

+		targetLabels.add(dflt);

+		for (final Label l : labels) {

+			targetLabels.add(l);

+		}

+		super.visitTableSwitchInsn(min, max, dflt, labels);

+	}

+

+	@Override

+	public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {

+		targetLabels.add(dflt);

+		for (final Label l : labels) {

+			targetLabels.add(l);

+		}

+		super.visitLookupSwitchInsn(dflt, keys, labels);

+	}

+

+	@Override

+	public void visitTryCatchBlock(Label start, Label end, Label handler,

+			String type) {

+		targetLabels.add(start);

+		targetLabels.add(end);

+		targetLabels.add(handler);

+		super.visitTryCatchBlock(start, end, handler, type);

+	}

+

+	@Override

+	public void visitEnd() {

+		accept(new BlockFinder());

+	}

+

+	private final class BlockFinder extends MethodAdapter {

+

+		private boolean blockStarted;

+

+		public BlockFinder() {

+			super(blockVisitor);

+			blockStarted = false;

+		}

+

+		private void onBlockEndBeforeJump() {

+			if (blockStarted) {

+				blockVisitor.visitBlockEndBeforeJump(blockCount);

+			}

+		}

+

+		private void onBlockEnd() {

+			if (blockStarted) {

+				blockVisitor.visitBlockEnd(blockCount);

+				blockCount++;

+				blockStarted = false;

+			}

+		}

+

+		@Override

+		public void visitLabel(Label label) {

+			if (targetLabels.contains(label)) {

+				onBlockEndBeforeJump();

+				onBlockEnd();

+			}

+			super.visitLabel(label);

+		}

+

+		@Override

+		public void visitJumpInsn(int opcode, Label label) {

+			blockStarted = true;

+			onBlockEndBeforeJump();

+			super.visitJumpInsn(opcode, label);

+			onBlockEnd();

+		}

+

+		@Override

+		public void visitInsn(int opcode) {

+			blockStarted = true;

+			switch (opcode) {

+			case Opcodes.RETURN:

+			case Opcodes.IRETURN:

+			case Opcodes.FRETURN:

+			case Opcodes.LRETURN:

+			case Opcodes.DRETURN:

+			case Opcodes.ARETURN:

+			case Opcodes.ATHROW:

+				onBlockEndBeforeJump();

+				super.visitInsn(opcode);

+				onBlockEnd();

+				break;

+			default:

+				super.visitInsn(opcode);

+				break;

+			}

+		}

+

+		@Override

+		public void visitTableSwitchInsn(int min, int max, Label dflt,

+				Label[] labels) {

+			blockStarted = true;

+			onBlockEndBeforeJump();

+			super.visitTableSwitchInsn(min, max, dflt, labels);

+			onBlockEnd();

+		}

+

+		@Override

+		public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {

+			blockStarted = true;

+			onBlockEndBeforeJump();

+			super.visitLookupSwitchInsn(dflt, keys, labels);

+			onBlockEnd();

+		}

+

+		@Override

+		public void visitFieldInsn(int opcode, String owner, String name,

+				String desc) {

+			blockStarted = true;

+			super.visitFieldInsn(opcode, owner, name, desc);

+		}

+

+		@Override

+		public void visitIincInsn(int var, int increment) {

+			blockStarted = true;

+			super.visitIincInsn(var, increment);

+		}

+

+		@Override

+		public void visitIntInsn(int opcode, int operand) {

+			blockStarted = true;

+			super.visitIntInsn(opcode, operand);

+		}

+

+		@Override

+		public void visitLdcInsn(Object cst) {

+			blockStarted = true;

+			super.visitLdcInsn(cst);

+		}

+

+		@Override

+		public void visitMethodInsn(int opcode, String owner, String name,

+				String desc) {

+			blockStarted = true;

+			super.visitMethodInsn(opcode, owner, name, desc);

+		}

+

+		@Override

+		public void visitMultiANewArrayInsn(String desc, int dims) {

+			blockStarted = true;

+			super.visitMultiANewArrayInsn(desc, dims);

+		}

+

+		@Override

+		public void visitTypeInsn(int opcode, String type) {

+			blockStarted = true;

+			super.visitTypeInsn(opcode, type);

+		}

+

+		@Override

+		public void visitVarInsn(int opcode, int var) {

+			blockStarted = true;

+			super.visitVarInsn(opcode, var);

+		}

+

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/CRC64.java b/org.jacoco.core/src/org/jacoco/core/instr/CRC64.java
new file mode 100644
index 0000000..b96fd51
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/CRC64.java
@@ -0,0 +1,55 @@
+package org.jacoco.core.instr;

+

+/**

+ * CRC64 checksum calculator based on the polynom specified in ISO 3309. The

+ * implementation is based on the following publications:

+ * 

+ * <ul>

+ * <li>http://en.wikipedia.org/wiki/Cyclic_redundancy_check</li>

+ * <li>http://www.geocities.com/SiliconValley/Pines/8659/crc.htm</li>

+ * </ul>

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public final class CRC64 {

+

+	private static final long POLY64REV = 0xd800000000000000L;

+

+	private static final long[] LOOKUPTABLE;

+

+	static {

+		LOOKUPTABLE = new long[0x100];

+		for (int i = 0; i < 0x100; i++) {

+			long v = i;

+			for (int j = 0; j < 8; j++) {

+				if ((v & 1) == 1) {

+					v = (v >>> 1) ^ POLY64REV;

+				} else {

+					v = (v >>> 1);

+				}

+			}

+			LOOKUPTABLE[i] = v;

+		}

+	}

+

+	/**

+	 * Calculates the CRC64 checksum for the given data array.

+	 * 

+	 * @param data

+	 *            data to calculate checksum for

+	 * @return checksum value

+	 */

+	public static long checksum(byte[] data) {

+		long sum = 0;

+		for (int i = 0; i < data.length; i++) {

+			final int lookupidx = ((int) sum ^ data[i]) & 0xff;

+			sum = (sum >>> 8) ^ LOOKUPTABLE[lookupidx];

+		}

+		return sum;

+	}

+

+	private CRC64() {

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/ClassAnalyzer.java b/org.jacoco.core/src/org/jacoco/core/instr/ClassAnalyzer.java
new file mode 100644
index 0000000..b9a3ddd
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/ClassAnalyzer.java
@@ -0,0 +1,73 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import org.jacoco.core.data.IClassStructureOutput;

+import org.jacoco.core.data.IMethodStructureOutput;

+import org.objectweb.asm.ClassVisitor;

+import org.objectweb.asm.MethodVisitor;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.commons.EmptyVisitor;

+

+/**

+ * A {@link ClassVisitor} that analyzes the executable blocks of a class.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class ClassAnalyzer extends EmptyVisitor {

+

+	private final IClassStructureOutput structureOutput;

+

+	private int methodCount;

+

+	/**

+	 * Creates a new analyzer that reports to the given

+	 * {@link IClassStructureOutput} instance.

+	 * 

+	 * @param structureOutput

+	 *            consumer for class structure output

+	 */

+	public ClassAnalyzer(IClassStructureOutput structureOutput) {

+		this.structureOutput = structureOutput;

+		methodCount = 0;

+	}

+

+	@Override

+	public void visitSource(String source, String debug) {

+		if (source != null) {

+			structureOutput.sourceFile(source);

+		}

+	}

+

+	@Override

+	public MethodVisitor visitMethod(int access, String name, String desc,

+			String signature, String[] exceptions) {

+

+		// Abstract methods do not have code to analyze

+		if ((access & Opcodes.ACC_ABSTRACT) != 0) {

+			return null;

+		}

+

+		final IMethodStructureOutput structure = structureOutput

+				.methodStructure(methodCount++, name, desc, signature);

+		return new BlockMethodAdapter(new MethodAnalyzer(structure), access,

+				name, desc, signature, exceptions);

+	}

+

+	@Override

+	public void visitEnd() {

+		structureOutput.end();

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/ClassInstrumenter.java b/org.jacoco.core/src/org/jacoco/core/instr/ClassInstrumenter.java
new file mode 100644
index 0000000..afe2fb1
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/ClassInstrumenter.java
@@ -0,0 +1,204 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import java.util.ArrayList;

+import java.util.List;

+

+import org.jacoco.core.runtime.IRuntime;

+import org.objectweb.asm.ClassAdapter;

+import org.objectweb.asm.ClassVisitor;

+import org.objectweb.asm.Label;

+import org.objectweb.asm.MethodVisitor;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.commons.EmptyVisitor;

+import org.objectweb.asm.commons.GeneratorAdapter;

+

+/**

+ * Adapter that instruments a class for coverage tracing.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class ClassInstrumenter extends ClassAdapter {

+

+	private static class EmptyBlockMethodVisitor extends EmptyVisitor implements

+			IBlockMethodVisitor {

+

+		public void visitBlockEndBeforeJump(final int id) {

+		}

+

+		public void visitBlockEnd(final int id) {

+		}

+

+	}

+

+	private final long id;

+

+	private final IRuntime runtime;

+

+	private final List<BlockMethodAdapter> blockCounters;

+

+	private Type type;

+

+	/**

+	 * Emits a instrumented version of this class to the given class visitor

+	 * 

+	 * @param id

+	 *            unique identifier given to this class

+	 * @param runtime

+	 *            this runtime will be used for instrumentation

+	 * @param cv

+	 *            next delegate in the visitor chain will receive the

+	 *            instrumented class

+	 */

+	public ClassInstrumenter(final long id, final IRuntime runtime,

+			final ClassVisitor cv) {

+		super(cv);

+		this.id = id;

+		this.runtime = runtime;

+		this.blockCounters = new ArrayList<BlockMethodAdapter>();

+	}

+

+	@Override

+	public void visit(final int version, final int access, final String name,

+			final String signature, final String superName,

+			final String[] interfaces) {

+		this.type = Type.getObjectType(name);

+		super.visit(version, access, name, signature, superName, interfaces);

+	}

+

+	@Override

+	public MethodVisitor visitMethod(final int access, final String name,

+			final String desc, final String signature, final String[] exceptions) {

+

+		final MethodVisitor mv = super.visitMethod(access, name, desc,

+				signature, exceptions);

+

+		// Abstract methods do not have code to analyze

+		if ((access & Opcodes.ACC_ABSTRACT) != 0) {

+			return mv;

+		}

+

+		final int methodId = blockCounters.size();

+

+		final IBlockMethodVisitor blockVisitor;

+		if (mv == null) {

+			blockVisitor = new EmptyBlockMethodVisitor();

+		} else {

+			blockVisitor = new MethodInstrumenter(mv, access, name, desc,

+					methodId, type);

+		}

+

+		final BlockMethodAdapter adapter = new BlockMethodAdapter(blockVisitor,

+				access, name, desc, signature, exceptions);

+		blockCounters.add(adapter);

+		return adapter;

+	}

+

+	@Override

+	public void visitEnd() {

+		createDataField();

+		createInitMethod();

+		super.visitEnd();

+	}

+

+	private void createDataField() {

+		super.visitField(GeneratorConstants.DATAFIELD_ACC,

+				GeneratorConstants.DATAFIELD_NAME,

+				GeneratorConstants.DATAFIELD_TYPE.getDescriptor(), null, null);

+	}

+

+	private void createInitMethod() {

+		final int access = GeneratorConstants.INIT_METHOD_ACC;

+		final String name = GeneratorConstants.INIT_METHOD.getName();

+		final String desc = GeneratorConstants.INIT_METHOD.getDescriptor();

+		final GeneratorAdapter gen = new GeneratorAdapter(super.visitMethod(

+				access, name, desc, null, null), access, name, desc);

+

+		// Load the value of the static data field:

+		gen.getStatic(type, GeneratorConstants.DATAFIELD_NAME,

+				GeneratorConstants.DATAFIELD_TYPE);

+		gen.dup();

+

+		// .............................................. Stack: [[Z, [[Z

+

+		// Skip initialization when we already have a data array:

+		final Label alreadyInitialized = new Label();

+		gen.ifNonNull(alreadyInitialized);

+

+		// .............................................. Stack: [[Z

+

+		gen.pop();

+		genInitializeDataField(gen);

+

+		// .............................................. Stack: [[Z

+

+		// Return the method's block array:

+		gen.visitLabel(alreadyInitialized);

+		gen.loadArg(0);

+		gen.arrayLoad(GeneratorConstants.BLOCK_ARR);

+		gen.returnValue();

+		gen.endMethod();

+	}

+

+	/**

+	 * Generates the byte code to initialize the static coverage data field

+	 * within this class.

+	 * 

+	 * The code will push the [[Z data array on the operand stack.

+	 * 

+	 * @param gen

+	 *            generator to emit code to

+	 */

+	private void genInitializeDataField(final GeneratorAdapter gen) {

+		genInstantiateDataArray(gen); // ................ Stack: [[Z

+		gen.dup(); // ................................... Stack: [[Z [[Z

+		gen.putStatic(type, GeneratorConstants.DATAFIELD_NAME,

+				GeneratorConstants.DATAFIELD_TYPE);

+

+		// .............................................. Stack: [[Z

+

+		gen.dup(); // ................................... Stack: [[Z [[Z

+		runtime.generateRegistration(id, gen);

+

+		// .............................................. Stack: [[Z

+	}

+

+	/**

+	 * Generates the byte code to instantiate the 2-dimensional block data

+	 * array. Each boolean[] entry is created in a length equals to the number

+	 * of blocks in the corresponding method.

+	 * 

+	 * The code will push the [[Z data array on the operand stack.

+	 * 

+	 * TODO: Let the coverage runtime generate this structure

+	 * 

+	 * @param gen

+	 *            generator to emit code to

+	 */

+	private void genInstantiateDataArray(final GeneratorAdapter gen) {

+		gen.push(blockCounters.size()); // .............. Stack: I

+		gen.newArray(GeneratorConstants.BLOCK_ARR); // .. Stack: [[Z

+		for (int blockIdx = 0; blockIdx < blockCounters.size(); blockIdx++) {

+			gen.dup(); // ............................... Stack: [[Z, [[Z

+			gen.push(blockIdx); // ...................... Stack: [[Z, [[Z, I

+			gen.push(blockCounters.get(blockIdx).getBlockCount());

+			// .......................................... Stack: [[Z, [[Z, I, I

+			gen.newArray(Type.BOOLEAN_TYPE);// .......... Stack: [[Z, [[Z, I, [Z

+			gen.arrayStore(GeneratorConstants.BLOCK_ARR); // Stack: [[Z

+		}

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/GeneratorConstants.java b/org.jacoco.core/src/org/jacoco/core/instr/GeneratorConstants.java
new file mode 100644
index 0000000..cb7ca29
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/GeneratorConstants.java
@@ -0,0 +1,66 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.commons.Method;

+

+/**

+ * Constants for generated instrumentation code.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public final class GeneratorConstants {

+

+	/**

+	 * Type for array of primitive boolean values. This type is used to store

+	 * covered blocks of a single method.

+	 */

+	public static final Type BLOCK_ARR = Type.getType("[Z");

+

+	// === Data Field ===

+

+	/**

+	 * Name of the field that stores coverage information of a class.

+	 */

+	public static final String DATAFIELD_NAME = "$jacocoData";

+

+	/**

+	 * Access modifiers of the field that stores coverage information of a

+	 * class.

+	 */

+	public static final int DATAFIELD_ACC = Opcodes.ACC_SYNTHETIC

+			| Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;

+

+	/**

+	 * The type of the field that stores coverage information of a class is a

+	 * 2-dimensional array of primitive boolean values.

+	 */

+	public static final Type DATAFIELD_TYPE = Type.getType("[[Z");

+

+	// === Init Method ===

+

+	/**

+	 * Initialization method that is added into every instrumented class.

+	 */

+	public static final Method INIT_METHOD = new Method("$jacocoInit", "(I)[Z");

+

+	/**

+	 * Access modifiers of the initialization method.

+	 */

+	public static final int INIT_METHOD_ACC = Opcodes.ACC_SYNTHETIC

+			| Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/IBlockMethodVisitor.java b/org.jacoco.core/src/org/jacoco/core/instr/IBlockMethodVisitor.java
new file mode 100644
index 0000000..243bed5
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/IBlockMethodVisitor.java
@@ -0,0 +1,43 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import org.objectweb.asm.MethodVisitor;

+

+/**

+ * A method visitor with additional notifications for block boundaries.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public interface IBlockMethodVisitor extends MethodVisitor {

+

+	/**

+	 * This method is called at the end of a block. If the last instruction of

+	 * the block may interrupt the control flow (e.g. jump or return) this

+	 * method is called right before this statement is visited.

+	 * 

+	 * @param id

+	 *            identifier of the block within the method

+	 */

+	public void visitBlockEndBeforeJump(int id);

+

+	/**

+	 * This method is always called after the last instruction of a block.

+	 * 

+	 * @param id

+	 *            identifier of the block within the method

+	 */

+	public void visitBlockEnd(int id);

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/ITargetLabelSource.java b/org.jacoco.core/src/org/jacoco/core/instr/ITargetLabelSource.java
new file mode 100644
index 0000000..a85b4be
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/ITargetLabelSource.java
@@ -0,0 +1,35 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import org.objectweb.asm.Label;

+

+/**

+ * Call-back interface to find labels used as control flow targets.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public interface ITargetLabelSource {

+

+	/**

+	 * Checks whether the given label is control flow target (jump, switch,

+	 * try/catch etc).

+	 * 

+	 * @param label

+	 *            label to check

+	 * @return <code>true</code>, if the label is a control flow target

+	 */

+	public boolean isTargetLabel(Label label);

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java
new file mode 100644
index 0000000..cb2ca20
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/Instrumenter.java
@@ -0,0 +1,90 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import org.jacoco.core.runtime.IRuntime;

+import org.objectweb.asm.ClassReader;

+import org.objectweb.asm.ClassVisitor;

+import org.objectweb.asm.ClassWriter;

+import org.objectweb.asm.Opcodes;

+

+/**

+ * Several APIs to instrument Java class definitions for coverage tracing.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class Instrumenter {

+

+	private final IRuntime runtime;

+

+	/**

+	 * Creates a new instance based on the given runtime.

+	 * 

+	 * @param runtime

+	 *            runtime used by the instrumented classes

+	 */

+	public Instrumenter(final IRuntime runtime) {

+		this.runtime = runtime;

+	}

+

+	/**

+	 * Creates a ASM adapter for a class with the given id.

+	 * 

+	 * @param classid

+	 *            id of the class calculated with {@link CRC64}

+	 * @param cv

+	 *            next class visitor in the chain

+	 * @return new visitor to write class definition to

+	 */

+	public ClassVisitor createInstrumentingVisitor(final long classid,

+			final ClassVisitor cv) {

+		return new ClassInstrumenter(classid, runtime, cv);

+	}

+

+	/**

+	 * Creates a instrumented version of the given class if possible.

+	 * 

+	 * @param reader

+	 *            definition of the class as ASM reader

+	 * @return instrumented definition or <code>null</code>

+	 * 

+	 */

+	public byte[] instrument(final ClassReader reader) {

+

+		// Don't instrument interfaces

+		if ((reader.getAccess() & Opcodes.ACC_INTERFACE) != 0) {

+			return null;

+		}

+

+		final ClassWriter writer = new ClassWriter(reader,

+				ClassWriter.COMPUTE_MAXS);

+		final ClassVisitor visitor = createInstrumentingVisitor(CRC64

+				.checksum(reader.b), writer);

+		reader.accept(visitor, 0);

+		return writer.toByteArray();

+	}

+

+	/**

+	 * Creates a instrumented version of the given class if possible.

+	 * 

+	 * @param buffer

+	 *            definition of the class

+	 * @return instrumented definition or <code>null</code>

+	 * 

+	 */

+	public byte[] instrument(final byte[] buffer) {

+		return instrument(new ClassReader(buffer));

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/IntSet.java b/org.jacoco.core/src/org/jacoco/core/instr/IntSet.java
new file mode 100644
index 0000000..17cc318
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/IntSet.java
@@ -0,0 +1,104 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import java.util.Arrays;

+

+/**

+ * Lightweight set of sorted int values. The implementation is designed for a

+ * small number of elements only.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+final class IntSet {

+

+	private int[] store;

+

+	private int size;

+

+	/**

+	 * Creates a new empty set with a initial capacity of 8 elements.

+	 */

+	public IntSet() {

+		this(8);

+	}

+

+	/**

+	 * Creates a new empty set with the given initial capacity.

+	 * 

+	 * @param initialCapacity

+	 *            this is the initial capacity

+	 */

+	public IntSet(int initialCapacity) {

+		this.store = new int[initialCapacity];

+		this.size = 0;

+	}

+

+	/**

+	 * Adds the given value to the set if it is not already contained.

+	 * 

+	 * @param value

+	 *            value to add

+	 * @return <code>true</code> if the value has actually been added

+	 */

+	public boolean add(int value) {

+		if (contains(value)) {

+			return false;

+		}

+		if (store.length == size) {

+			final int[] newStore = new int[size * 2];

+			System.arraycopy(store, 0, newStore, 0, size);

+			store = newStore;

+		}

+		store[size++] = value;

+		return true;

+	}

+

+	/**

+	 * Clears all elements from the set.

+	 */

+	public void clear() {

+		size = 0;

+	}

+

+	/**

+	 * Tests whether the given value is in this set.

+	 * 

+	 * @param value

+	 *            value to check

+	 * @return <code>true</code> if the value is contained

+	 */

+	public boolean contains(int value) {

+		// search backwards as the last value is typically added again

+		for (int i = size; --i >= 0;) {

+			if (store[i] == value) {

+				return true;

+			}

+		}

+		return false;

+	}

+

+	/**

+	 * Returns a sorted array of the current content.

+	 * 

+	 * @return sorted array of the current content

+	 */

+	public int[] toArray() {

+		final int[] result = new int[size];

+		System.arraycopy(store, 0, result, 0, size);

+		Arrays.sort(result);

+		return result;

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/MethodAnalyzer.java b/org.jacoco.core/src/org/jacoco/core/instr/MethodAnalyzer.java
new file mode 100644
index 0000000..cd35dff
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/MethodAnalyzer.java
@@ -0,0 +1,146 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import org.jacoco.core.data.IMethodStructureOutput;

+import org.objectweb.asm.Label;

+import org.objectweb.asm.commons.EmptyVisitor;

+

+/**

+ * This {@link IBlockMethodVisitor} analyzes the block structure of a method and

+ * reports it to a {@link IMethodStructureOutput} instance.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public final class MethodAnalyzer extends EmptyVisitor implements

+		IBlockMethodVisitor {

+

+	private static final int NO_LINE_INFO = -1;

+

+	private final IMethodStructureOutput structureOutput;

+

+	private int instructionCount;

+

+	private int currentLine;

+

+	private final IntSet lineNumbers;

+

+	/**

+	 * Creates a new analyzer that reports to the given

+	 * {@link IMethodStructureOutput} instance.

+	 * 

+	 * @param structureOutput

+	 *            consumer for method structure events

+	 */

+	public MethodAnalyzer(IMethodStructureOutput structureOutput) {

+		this.structureOutput = structureOutput;

+		this.instructionCount = 0;

+		this.currentLine = NO_LINE_INFO;

+		this.lineNumbers = new IntSet();

+	}

+

+	private void addInstruction() {

+		instructionCount++;

+		if (currentLine != NO_LINE_INFO) {

+			lineNumbers.add(currentLine);

+		}

+	}

+

+	// === MethodVisitor ===

+

+	@Override

+	public void visitLineNumber(int line, Label start) {

+		currentLine = line;

+	}

+

+	@Override

+	public void visitJumpInsn(int opcode, Label label) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitInsn(int opcode) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitFieldInsn(int opcode, String owner, String name,

+			String desc) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitIincInsn(int var, int increment) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitIntInsn(int opcode, int operand) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitLdcInsn(Object cst) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitMethodInsn(int opcode, String owner, String name,

+			String desc) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitMultiANewArrayInsn(String desc, int dims) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitTableSwitchInsn(int min, int max, Label dflt,

+			Label[] labels) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitTypeInsn(int opcode, String type) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitVarInsn(int opcode, int var) {

+		addInstruction();

+	}

+

+	@Override

+	public void visitEnd() {

+		structureOutput.end();

+	}

+

+	// === IBlockVisitor ===

+

+	public void visitBlockEndBeforeJump(int id) {

+	}

+

+	public void visitBlockEnd(int id) {

+		structureOutput.block(id, instructionCount, lineNumbers.toArray());

+		instructionCount = 0;

+		lineNumbers.clear();

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/MethodInstrumenter.java b/org.jacoco.core/src/org/jacoco/core/instr/MethodInstrumenter.java
new file mode 100644
index 0000000..fc7c6ee
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/MethodInstrumenter.java
@@ -0,0 +1,92 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.instr;

+

+import org.objectweb.asm.MethodVisitor;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+import org.objectweb.asm.commons.GeneratorAdapter;

+

+/**

+ * This method adapter instruments a method to record every block that gets

+ * fully executed.

+ * 

+ * TODO The instrumented method may need a increased stack but this adapter will

+ * *not* adjust the max stack size value. Therefore the ClassWriter needs to be

+ * invoked with COMPUTE_MAXS. For performance optimization this adapter should

+ * adjust the directly calculate the max stack size and report it properly.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class MethodInstrumenter extends GeneratorAdapter implements

+		IBlockMethodVisitor {

+

+	private final int methodId;

+

+	private final Type enclosingType;

+

+	private int blockArray;

+

+	/**

+	 * Create a new instrumenter instance for the given method.

+	 * 

+	 * @param mv

+	 *            next method visitor in the chain

+	 * @param access

+	 *            access flags for the method

+	 * @param name

+	 *            name of the method

+	 * @param desc

+	 *            description of the method

+	 * @param methodId

+	 *            unique id of the method within its enclosing type

+	 * @param enclosingType

+	 *            type enclosing this method

+	 */

+	public MethodInstrumenter(MethodVisitor mv, int access, String name,

+			String desc, int methodId, Type enclosingType) {

+		super(mv, access, name, desc);

+		this.methodId = methodId;

+		this.enclosingType = enclosingType;

+	}

+

+	@Override

+	public void visitCode() {

+		super.visitCode();

+		// At the very beginning of the method we load the boolean[] array into

+		// a local variable that stores the block coverage of this method.

+

+		push(methodId); // ................................... Stack: I

+		invokeStatic(enclosingType, GeneratorConstants.INIT_METHOD); // ... Stack: [Z

+		blockArray = newLocal(GeneratorConstants.BLOCK_ARR);

+		storeLocal(blockArray); // ........................... Stack: <empty>

+	}

+

+	// === IBlockMethodVisitor ===

+

+	public void visitBlockEndBeforeJump(int id) {

+		// At the end of every block we set the corresponding position in the

+		// boolean[] array to true.

+

+		loadLocal(blockArray); // ............................ Stack: [Z

+		push(id); // ......................................... Stack: [Z, I

+		push(1); // .......................................... Stack: [Z, I, I

+		visitInsn(Opcodes.BASTORE); // ....................... Stack: <empty>

+	}

+

+	public void visitBlockEnd(int id) {

+		// nothing to do here

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/instr/package.html b/org.jacoco.core/src/org/jacoco/core/instr/package.html
new file mode 100644
index 0000000..7ae30a9
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/instr/package.html
@@ -0,0 +1,16 @@
+<html>

+<body>

+<p>

+  This package contains the classes to analyze and instrument classes for code

+  coverage. The main entry points are:

+</p>

+

+<ul>

+  <li><a href="Analyzer.html">Analyzer</a>: Class structure information for

+  analysis and report generation.</li>

+  <li><a href="Instrumenter.html">Instrumenter</a>: Classes instrumentation for

+  tracing coverage at runtime.</li>

+</ul>

+

+</body>

+</html>

diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java
new file mode 100644
index 0000000..273321a
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/IRuntime.java
@@ -0,0 +1,77 @@
+/*******************************************************************************

+ * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Marc R. Hoffmann - initial API and implementation

+ *    

+ * $Id: $

+ *******************************************************************************/

+package org.jacoco.core.runtime;

+

+import org.jacoco.core.data.IExecutionDataOutput;

+import org.objectweb.asm.commons.GeneratorAdapter;

+

+/**

+ * This interface represents a particular mechanism to collect execution

+ * information in the target VM at runtime.

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public interface IRuntime {

+

+	/**

+	 * This method generates the byte code required to register the coverage

+	 * data structure of the class with the given id. Typically the

+	 * instrumentation process will embed this code into a method that is called

+	 * on class initialization. This method can be called at any time even

+	 * outside the target VM.

+	 * 

+	 * The generated code must pop a <code>byte[][]</code> instance from the

+	 * operand stack. Except this object on the stack the generated code must

+	 * not make any assumptions about the structure of the embedding method or

+	 * class.

+	 * 

+	 * @param classId

+	 *            identifier of the class

+	 * @param gen

+	 *            code output

+	 */

+	public void generateRegistration(long classId, GeneratorAdapter gen);

+

+	/**

+	 * Starts the coverage runtime. This method MUST be called before any class

+	 * instrumented for this runtime is loaded.

+	 */

+	public void startup();

+

+	/**

+	 * Allows the coverage runtime to cleanup internals. This class should be

+	 * called when classes instrumented for this runtime are not used any more.

+	 */

+	public void shutdown();

+

+	/**

+	 * Collects the current execution data and writes it to the given

+	 * {@link IExecutionDataOutput} object. This method must only be called

+	 * between {@link #startup()} and {@link #shutdown()}.

+	 * 

+	 * @param output

+	 *            handler to write coverage data to

+	 * @param reset

+	 *            if <code>true</code> the current coverage information is also

+	 *            cleared

+	 */

+	public void collect(IExecutionDataOutput output, boolean reset);

+

+	/**

+	 * Resets all coverage information. This method must only be called between

+	 * {@link #startup()} and {@link #shutdown()}.

+	 */

+	public void reset();

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/SystemPropertiesRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/SystemPropertiesRuntime.java
new file mode 100644
index 0000000..a0948d8
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/SystemPropertiesRuntime.java
@@ -0,0 +1,126 @@
+package org.jacoco.core.runtime;

+

+import java.util.Arrays;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.Map;

+

+import org.jacoco.core.data.IExecutionDataOutput;

+import org.jacoco.core.instr.GeneratorConstants;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.commons.GeneratorAdapter;

+

+/**

+ * This {@link IRuntime} implementation places the coverage data in the

+ * {@link System#getProperties()} hash table. The advantage is, that the

+ * instrumented classes do not get dependencies to other classes than the JRE

+ * library itself.

+ * 

+ * This runtime may cause problems in environments with security restrictions,

+ * in applications that replace the system properties or in applications that

+ * fail if non-String values are placed in the system properties.

+ * 

+ * 

+ * @author Marc R. Hoffmann

+ * @version $Revision: $

+ */

+public class SystemPropertiesRuntime implements IRuntime {

+

+	private static final String KEYPREFIX = "jacoco-";

+

+	private final String key;

+

+	/**

+	 * Creates a new runtime with the given id. The id helps to separate

+	 * different runtime instances. The instrumentation and the target VM must

+	 * be based on a runtime with the same id.

+	 * 

+	 * @param id

+	 *            Identifier for the runtime

+	 */

+	public SystemPropertiesRuntime(int id) {

+		this.key = KEYPREFIX + Integer.toHexString(id);

+	}

+

+	/**

+	 * Creates a new runtime with a random identifier.

+	 */

+	public SystemPropertiesRuntime() {

+		this.key = KEYPREFIX + hashCode();

+	}

+

+	// TODO: lokale Variable vermeiden (swap!)

+	public void generateRegistration(long classId, GeneratorAdapter gen) {

+

+		// boolean[][] data = pop()

+		final int data = gen.newLocal(GeneratorConstants.DATAFIELD_TYPE);

+		gen.storeLocal(data);

+

+		// Properties stack := System.getProperties()

+		gen.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System",

+				"getProperties", "()Ljava/util/Properties;");

+

+		// gen.swap();

+

+		// Map stack := stack.get(key)

+		gen.push(key);

+		gen.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Properties",

+				"get", "(Ljava/lang/Object;)Ljava/lang/Object;");

+		gen.visitTypeInsn(Opcodes.CHECKCAST, "java/util/Map");

+

+		// stack.put(classId, data)

+		gen.push(classId);

+		gen.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf",

+				"(J)Ljava/lang/Long;");

+		// gen.swap();

+		gen.loadLocal(data);

+		gen.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "put",

+				"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

+		gen.pop();

+	}

+

+	public void startup() {

+		final Map<Long, boolean[][]> dataMap = Collections

+				.synchronizedMap(new HashMap<Long, boolean[][]>());

+		System.getProperties().put(key, dataMap);

+	}

+

+	@SuppressWarnings("unchecked")

+	private Map<Long, boolean[][]> getDataMap() {

+		final Object object = System.getProperties().get(key);

+		if (object == null) {

+			throw new IllegalStateException("Runtime not started.");

+		}

+		return (Map<Long, boolean[][]>) object;

+	}

+

+	public void collect(IExecutionDataOutput output, boolean reset) {

+		final Map<Long, boolean[][]> dataMap = getDataMap();

+		synchronized (dataMap) {

+			for (Map.Entry<Long, boolean[][]> entry : dataMap.entrySet()) {

+				final long classId = entry.getKey().longValue();

+				final boolean[][] blockData = entry.getValue();

+				output.classExecution(classId, blockData);

+			}

+			if (reset) {

+				reset();

+			}

+		}

+	}

+

+	public void reset() {

+		final Map<Long, boolean[][]> dataMap = getDataMap();

+		synchronized (dataMap) {

+			for (boolean[][] data : dataMap.values()) {

+				for (boolean[] arr : data) {

+					Arrays.fill(arr, false);

+				}

+			}

+		}

+	}

+

+	public void shutdown() {

+		System.getProperties().remove(key);

+	}

+

+}

diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/package.html b/org.jacoco.core/src/org/jacoco/core/runtime/package.html
new file mode 100644
index 0000000..274480e
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/package.html
@@ -0,0 +1,9 @@
+<html>

+<body>

+

+<p>

+  This package contains the classes to collect execution data at runtime.

+</p>

+

+</body>

+</html>

diff --git a/org.jacoco.core/src/overview.html b/org.jacoco.core/src/overview.html
new file mode 100644
index 0000000..370fd29
--- /dev/null
+++ b/org.jacoco.core/src/overview.html
@@ -0,0 +1,31 @@
+<html>

+<body>

+

+<p>

+  The JaCoCo core bundle implements the code coverage technology itself. It 

+  provides APIs and implementation for

+</p>

+

+<ul>  

+  <li>class file analysis and instrumentation</li>

+  <li>collecting execution data at runtime and</li> 

+  <li>calculating and storing coverage data.</li> 

+</ul>

+

+<pre>

+

+  |  Class files    |  Runtime        |  Output           Coverage Report   

+

+

+  Analysis ----------------------------- IStructureDataOutput  \

+                                                                +---- Coverage Data

+  Instrumentation --- ExecutionData ---- IExecutionDataOutput  /

+

+

+</pre>

+

+

+

+

+</body>

+</html>
\ No newline at end of file