diff options
Diffstat (limited to 'org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java')
-rw-r--r-- | org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java new file mode 100644 index 00000000..7cbe989f --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java @@ -0,0 +1,197 @@ +// BEGIN android-change +package org.jacoco.core.data; + +import java.io.IOException; +import java.nio.channels.FileChannel; + +/** + * Class that delegates calls to {@link IExecutionData} interface methods to another instance. + * Also has the ability to convert the underlying implementation to a {@link MappedExecutionData} + * instance. + */ +public class ExecutionDataDelegate implements IExecutionData { + private IExecutionData delegate; + + public ExecutionDataDelegate( + final long id, final String name, final int probeCount, final FileChannel channel) { + if ((channel != null) && canMapData(name)) { + try { + delegate = new MappedExecutionData(id, name, probeCount, channel); + } catch (IOException e) { + delegate = new ExecutionData(id, name, probeCount); + } + } else { + delegate = new ExecutionData(id, name, probeCount); + } + } + + /** + * Converts the existing delegate into a {@link MappedExecutionData} instance if it is not + * already one, and copies any probe data into the new instance. + */ + public synchronized void convert(final FileChannel channel) throws IOException { + if (!(delegate instanceof MappedExecutionData) && canMapData(getName())) { + IExecutionData newDelegate = new MappedExecutionData( + getId(), getName(), getProbeCount(), channel); + newDelegate.merge(delegate); + delegate = newDelegate; + } + } + + /** + * Determines if a class can be converted to memory-mapped. + */ + private static boolean canMapData(final String name) { + if (name.startsWith("android/app/") + || name.startsWith("android/os/") + || name.startsWith("com/android/internal/util/") + || name.startsWith("java/")) { + return false; + } + return true; + } + + /** + * Return the unique identifier for this class. The identifier is the CRC64 + * checksum of the raw class file definition. + * + * @return class identifier + */ + public long getId() { + return delegate.getId(); + } + + /** + * The VM name of the class. + * + * @return VM name + */ + public String getName() { + return delegate.getName(); + } + + /** + * The number of instrumentation probes for this class. + * + * @return number of probes + */ + public int getProbeCount() { + return delegate.getProbeCount(); + } + + /** + * Returns a copy of the probe data as a boolean array. + * + * Changes to the returned array will not be reflected in the execution data. + * + * @return copy of the probe data + */ + public boolean[] getProbesCopy() { + return delegate.getProbesCopy(); + } + + /** + * Sets all probes to <code>false</code>. + */ + public void reset() { + delegate.reset(); + } + + /** + * Checks whether any probe has been hit. + * + * @return <code>true</code>, if at least one probe has been hit + */ + public boolean hasHits() { + return delegate.hasHits(); + } + + /** + * Merges the given execution data into the probe data of this object. I.e. + * a probe entry in this object is marked as executed (<code>true</code>) if + * this probe or the corresponding other probe was executed. So the result + * is + * + * <pre> + * A or B + * </pre> + * + * The probe array of the other object is not modified. + * + * @param other + * execution data to merge + */ + public void merge(final IExecutionData other) { + delegate.merge(other); + } + + /** + * Merges the given execution data into the probe data of this object. A + * probe in this object is set to the value of <code>flag</code> if the + * corresponding other probe was executed. For <code>flag==true</code> this + * corresponds to + * + * <pre> + * A or B + * </pre> + * + * For <code>flag==false</code> this can be considered as a subtraction + * + * <pre> + * A and not B + * </pre> + * + * The probe array of the other object is not modified. + * + * @param other + * execution data to merge + * @param flag + * merge mode + */ + public void merge(final IExecutionData other, boolean flag) { + delegate.merge(other, flag); + } + + /** + * Asserts that this execution data object is compatible with the given + * parameters. The purpose of this check is to detect a very unlikely class + * id collision. + * + * @param id + * other class id, must be the same + * @param name + * other name, must be equal to this name + * @param probecount + * probe data length, must be the same as for this data + * @throws IllegalStateException + * if the given parameters do not match this instance + */ + public void assertCompatibility(final long id, final String name, final int probeCount) + throws IllegalStateException { + delegate.assertCompatibility(id, name, probeCount); + } + + /** + * Returns the execution data probe for a given index. A value of + * <code>true</code> indicates that the corresponding probe was + * executed. + * + * @param index the probe's index to look up + * + * @return probe data + */ + public boolean getProbe(final int index) { + return delegate.getProbe(index); + } + + /** + * Sets the execution data probe at the given index to <code>true</code>. + * + * @param index the probe's index to set + * @param value the value to set the probe to + */ + public void setProbe(final int index) { + delegate.setProbe(index); + } + } + // END android-change |