public interface JVoidConfiguration {

    String dbUrl();

    String dbUsername();

    String dbPassword();

    String basePackage();

    String excludes();

    String includes();

    Boolean heuristicExcludeCglib();

    Boolean heuristicExcludeJacoco();

    Boolean heuristicExcludeGroovyCallSite();

} @Singleton
public class JVoidExecutionContext {

    private ExecutionsRepository executionsRepository;

    private JExecution currentExecution;

    private ThreadLocal<JTest> runningTestHolder = new ThreadLocal<>();

    @Inject
    public JVoidExecutionContext(ExecutionsRepository executionsRepository) {
        super();
        this.executionsRepository = executionsRepository;
        this.runningTestHolder.set(null);
    }

    public Long getCurrentExecutionId() {
        return currentExecution == null ? null : currentExecution.getId();
    }

    public JExecution getCurrentExecution() {
        return currentExecution;
    }

    public void setCurrentExecution(JExecution currentExecution) {
        this.currentExecution = currentExecution;
    }

    public void startNewExecution() {
        JExecution execution = new JExecution();
        execution.setTimestamp(System.currentTimeMillis());
        execution = executionsRepository.add(execution);
        currentExecution = execution;
    }

    public JTest getRunningTest() {
        return runningTestHolder.get();
    }

    public synchronized void setRunningTest(JTest runningTest) {
        runningTestHolder.set(runningTest);
    }
} @Singleton
public class ProviderUtil {

    public String getClassIdentifier(CtClass clazz) {
        return clazz.getName();
    }

    public String getConstructorIdentifier(CtConstructor constructor) {
        return constructor.getLongName();
    }

    public String getMethodIdentifier(CtMethod method) {
        return method.getLongName();
    }

} public interface ClassHandler {

    void handleClass(CtClass ctClass) throws CannotCompileException;

} @Singleton
public class CodeChecksummer {

    private CtClassChecksummer ctClassChecksummer;
    private CtBehaviorChecksummer ctBehaviorChecksummer;
    private CtMethodChecksummer ctMethodChecksummer;

    @Inject
    public CodeChecksummer(CtClassChecksummer ctClassChecksummer, CtBehaviorChecksummer ctBehaviorChecksummer, CtMethodChecksummer ctMethodChecksummer) {
        this.ctClassChecksummer = ctClassChecksummer;
        this.ctBehaviorChecksummer = ctBehaviorChecksummer;
        this.ctMethodChecksummer = ctMethodChecksummer;
    }

    public String checksum(CtClass input) {
        return ctClassChecksummer.checksum(input);
    }

    public String checksum(CtMethod input) {
        return ctMethodChecksummer.checksum(input);
    }

    public String checksum(CtBehavior input) {
        return ctBehaviorChecksummer.checksum(input);
    }
} @Data
public class JClass implements JEntity<Long>, ChecksumAware {

    private Long id;
    private Long executionId;
    private String identifier;
    private String checksum;
    private String superClassIdentifier;
    
} @Data
public class JClassConstructor implements JEntity<Long>, ChecksumAware {

    private Long id;
    private String identifier;
    private String checksum;
    private Long classId;
    
} @Data
public class JClassStaticBlock implements JEntity<Long>, ChecksumAware {

    private Long id;
    private String identifier;
    private String checksum;
    private Long classId;
    
} @Singleton
public class ClassConstructorsRepository extends AbstractRepository<JClassConstructor, Long>
        implements TestRelatedEntityRepository<JClassConstructor, Long> {
    private ResultSetHandler<JClassConstructor> objectHandler = new BeanHandler<>(
            JClassConstructor.class);
    private ResultSetHandler<Map<String, JClassConstructor>> identifierMapHandler = new BeanMapHandler<>(
            JClassConstructor.class, "identifier");

    @Inject
    public ClassConstructorsRepository(MetadataDatabase database) {
        super(database);
    }

    @Override
    public JClassConstructor findById(Long id) {
        return query("SELECT * FROM class_constructors WHERE id = ?", objectHandler, id);
    }

    @Override
    public JClassConstructor add(JClassConstructor jconstructor) {
        assertNull(jconstructor.getId());
        String sql = "INSERT INTO class_constructors (classId, identifier, checksum) VALUES (?, ?, ?)";
        long id = executeInsert(sql,jconstructor.getClassId(), jconstructor.getIdentifier(), jconstructor.getChecksum());
        jconstructor.setId(id);
        return jconstructor;
    }

    @Override
    public Map<String, JClassConstructor> findByTestId(Long testId) {
        // @formatter:off
        String sql = "SELECT cc.* FROM test_classes tc "
                + " INNER JOIN classes c ON tc.classId = c.id "
                + " INNER JOIN class_constructors cc ON cc.classId = c.id WHERE tc.testId = ? ";
        // @formatter:on
        return query(sql, identifierMapHandler, testId);
    }

    @Override
    public Map<String, JClassConstructor> findByExecutionIdAndRelatedToTestId(Long executionId,
            Long testId) {
        // @formatter:off
        String sql = "SELECT cc.* FROM class_constructors cc "
                + " INNER JOIN classes c ON cc.classId = c.id "
                + " WHERE c.executionId = ? "
                + " AND cc.identifier IN ("
                + " SELECT cc.identifier FROM test_classes tc "
                + "  INNER JOIN classes c ON c.id = tc.classId "
                + "  INNER JOIN class_constructors cc ON cc.classId = c.id "
                + "  WHERE tc.testId = ? "
                + "  GROUP BY cc.identifier ) ";
        // @formatter:on
        return query(sql, identifierMapHandler, executionId, testId);
    }
} @Singleton
public class ClassStaticBlocksRepository extends AbstractRepository<JClassStaticBlock, Long>
        implements TestRelatedEntityRepository<JClassStaticBlock, Long> {
    private ResultSetHandler<JClassStaticBlock> objectHandler = new BeanHandler<>(
            JClassStaticBlock.class);
    private ResultSetHandler<Map<String, JClassStaticBlock>> identifierMapHandler = new BeanMapHandler<>(
            JClassStaticBlock.class, "identifier");

    @Inject
    public ClassStaticBlocksRepository(MetadataDatabase database) {
        super(database);
    }

    @Override
    public JClassStaticBlock findById(Long id) {
        return query("SELECT * FROM class_static_blocks WHERE id = ?", objectHandler, id);
    }

    @Override
    public JClassStaticBlock add(JClassStaticBlock jstaticblock) {
        assertNull(jstaticblock.getId());
        String sql = "INSERT INTO class_static_blocks (classId, identifier, checksum) VALUES (?, ?, ?)";
        long id = executeInsert(sql, jstaticblock.getClassId(), jstaticblock.getIdentifier(), jstaticblock.getChecksum());
        jstaticblock.setId(id);
        return jstaticblock;
    }

    @Override
    public Map<String, JClassStaticBlock> findByTestId(Long testId) {
        // @formatter:off
        String sql = "SELECT csb.* FROM test_classes tc "
                + " INNER JOIN classes c ON tc.classId = c.id "
                + " INNER JOIN class_static_blocks csb ON csb.classId = c.id "
                + "WHERE tc.testId = ?";
        // @formatter:on
        return query(sql, identifierMapHandler, testId);
    }

    @Override
    public Map<String, JClassStaticBlock> findByExecutionIdAndRelatedToTestId(Long executionId,
            Long testId) {
        // @formatter:off
        String sql = "SELECT csb.* FROM class_static_blocks csb "
                + " INNER JOIN classes c ON csb.classId = c.id " + " WHERE c.executionId = ? "
                + " AND csb.identifier IN (" 
                + "  SELECT csb.identifier "
                + "  FROM test_classes tc "
                + "   INNER JOIN classes c ON c.id = tc.classId "
                + "   INNER JOIN class_static_blocks csb ON csb.classId = c.id "
                + "  WHERE tc.testId = ? "
                + "  GROUP BY csb.identifier ) ";
        // @formatter:on
        return query(sql, identifierMapHandler, executionId, testId);
    }

} @Singleton
public class ClassesRepository extends AbstractRepository<JClass, Long>implements TestRelatedEntityRepository<JClass, Long> {
    private ResultSetHandler<JClass> objectHandler = new BeanHandler<>(JClass.class);
    private ResultSetHandler<Map<String, JClass>> identifierMapHandler = new BeanMapHandler<>(JClass.class, "identifier");

    @Inject
    public ClassesRepository(MetadataDatabase database) {
        super(database);
    }

    @Override
    public JClass findById(Long id) {
        return query("SELECT * FROM classes WHERE id = ?", objectHandler, id);
    }

    @Override
    public JClass add(JClass jclass) {
        assertNull(jclass.getId());
        String sql = "INSERT INTO classes " + "(executionId, identifier, checksum, superclassidentifier) " + "VALUES (?, ?, ?, ?)";
        long id = executeInsert(sql, jclass.getExecutionId(), jclass.getIdentifier(), jclass.getChecksum(), jclass.getSuperClassIdentifier());

        jclass.setId(id);

        return jclass;
    }

    public JClass findByIdenfifierAndExecutionId(String identifier, long executionId) {
        return query("SELECT c.* FROM classes c WHERE c.identifier = ? AND c.executionId = ?", objectHandler, identifier, executionId);
    }

    @Override
    public Map<String, JClass> findByTestId(Long testId) {
        return query("SELECT c.* FROM test_classes tc INNER JOIN classes c ON c.id = tc.classId WHERE tc.testId = ?", identifierMapHandler, testId);
    }

    @Override
    public Map<String, JClass> findByExecutionIdAndRelatedToTestId(Long executionId, Long testId) {
        // @formatter:off
        String sql = "SELECT c.* FROM classes c " + 
                     "WHERE c.executionId = ? " + 
                     " AND c.identifier IN (" + 
                     "  SELECT c.identifier " +
                     "  FROM test_classes tc " + 
                     "   INNER JOIN classes c ON c.id = tc.classId " +
                     "  WHERE tc.testId = ? " + 
                     "  GROUP BY c.identifier )";
        // @formatter:on
        return query(sql, identifierMapHandler, executionId, testId);
    }

}
import com.google.inject.Inject;
import io.jvoid.configuration.JVoidConfiguration;
import io.jvoid.execution.JVoidExecutionContext;
import io.jvoid.instrumentation.provider.ProviderUtil;
import io.jvoid.instrumentation.provider.api.ClassHandler;
import io.jvoid.metadata.checksum.CodeChecksummer;
import io.jvoid.metadata.model.JClass;
import io.jvoid.metadata.model.JClassConstructor;
import io.jvoid.metadata.model.JClassStaticBlock;
import io.jvoid.metadata.repositories.ClassConstructorsRepository;
import io.jvoid.metadata.repositories.ClassStaticBlocksRepository;
import io.jvoid.metadata.repositories.ClassesRepository;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.NotFoundException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
package io.jvoid.instrumentation.provider.app;




/**
 * Handle all the tracked application classes that are semantically under test
 * or will affect test executions. In particular, it will keep track of all matching
 * application classes and store the metadata in the persistence storage used by
 * JVoid given the current configuration.
 *
 */
@Slf4j
@AllArgsConstructor(onConstructor=@__({@Inject}))
public class AppClassHandler implements ClassHandler {