protected void configureEclipseClasspath(Project project, SourceSet testIntegrationSourceSet) {

    EclipseModel eclipseModel = GradleUtil.getExtension(project, EclipseModel.class);

    EclipseClasspath eclipseClasspath = eclipseModel.getClasspath();

    Collection<Configuration> plusConfigurations = eclipseClasspath.getPlusConfigurations();

    Configuration configuration =
        GradleUtil.getConfiguration(
            project, testIntegrationSourceSet.getRuntimeConfigurationName());

    plusConfigurations.add(configuration);
  }
  protected void configureTaskCheck(Test test) {
    Project project = test.getProject();

    Task task = GradleUtil.getTask(project, LifecycleBasePlugin.CHECK_TASK_NAME);

    task.dependsOn(test);
  }
  protected void configureIdeaModule(Project project, SourceSet testIntegrationSourceSet) {

    IdeaModel ideaModel = GradleUtil.getExtension(project, IdeaModel.class);

    IdeaModule ideaModule = ideaModel.getModule();

    Map<String, Map<String, Collection<Configuration>>> scopes = ideaModule.getScopes();

    Map<String, Collection<Configuration>> testScope = scopes.get("TEST");

    Collection<Configuration> plusConfigurations = testScope.get("plus");

    Configuration configuration =
        GradleUtil.getConfiguration(
            project, testIntegrationSourceSet.getRuntimeConfigurationName());

    plusConfigurations.add(configuration);
  }
  @Override
  public void apply(Project project) {
    GradleUtil.applyPlugin(project, JavaPlugin.class);

    SourceSet testIntegrationSourceSet = addSourceSetTestIntegration(project);

    Test testIntegrationTask = addTaskTestIntegration(project, testIntegrationSourceSet);

    configureEclipse(project, testIntegrationSourceSet);
    configureIdea(project, testIntegrationSourceSet);
    configureTaskCheck(testIntegrationTask);
  }
  protected SourceSet addSourceSetTestIntegration(Project project) {
    SourceSet testIntegrationSourceSet =
        GradleUtil.addSourceSet(project, TEST_INTEGRATION_SOURCE_SET_NAME);

    Configuration testIntegrationCompileConfiguration =
        GradleUtil.getConfiguration(
            project, testIntegrationSourceSet.getCompileConfigurationName());

    Configuration testCompileConfiguration =
        GradleUtil.getConfiguration(project, JavaPlugin.TEST_COMPILE_CONFIGURATION_NAME);

    testIntegrationCompileConfiguration.extendsFrom(testCompileConfiguration);

    Configuration testIntegrationRuntimeConfiguration =
        GradleUtil.getConfiguration(
            project, testIntegrationSourceSet.getRuntimeConfigurationName());

    Configuration testRuntimeConfiguration =
        GradleUtil.getConfiguration(project, JavaPlugin.TEST_RUNTIME_CONFIGURATION_NAME);

    testIntegrationRuntimeConfiguration.extendsFrom(
        testRuntimeConfiguration, testIntegrationCompileConfiguration);

    SourceSet mainSourceSet = GradleUtil.getSourceSet(project, SourceSet.MAIN_SOURCE_SET_NAME);

    FileCollection compileClasspath = testIntegrationSourceSet.getCompileClasspath();

    testIntegrationSourceSet.setCompileClasspath(compileClasspath.plus(mainSourceSet.getOutput()));

    FileCollection runtimeClasspath = testIntegrationSourceSet.getRuntimeClasspath();

    testIntegrationSourceSet.setRuntimeClasspath(runtimeClasspath.plus(mainSourceSet.getOutput()));

    return testIntegrationSourceSet;
  }
  protected Test addTaskTestIntegration(Project project, final SourceSet testIntegrationSourceSet) {

    final Test test = GradleUtil.addTask(project, TEST_INTEGRATION_TASK_NAME, Test.class);

    test.mustRunAfter(JavaPlugin.TEST_TASK_NAME);

    test.setDescription("Runs the integration tests.");
    test.setForkEvery(null);
    test.setGroup(JavaBasePlugin.VERIFICATION_GROUP);

    ConventionMapping conventionMapping = test.getConventionMapping();

    conventionMapping.map(
        "classpath",
        new Callable<FileCollection>() {

          @Override
          public FileCollection call() throws Exception {
            return testIntegrationSourceSet.getRuntimeClasspath();
          }
        });

    conventionMapping.map(
        "testClassesDir",
        new Callable<File>() {

          @Override
          public File call() throws Exception {
            SourceSetOutput sourceSetOutput = testIntegrationSourceSet.getOutput();

            return sourceSetOutput.getClassesDir();
          }
        });

    project.afterEvaluate(
        new Action<Project>() {

          @Override
          public void execute(Project project) {
            Set<String> includes = test.getIncludes();

            if (includes.isEmpty()) {
              test.setIncludes(Collections.singleton("**/*Test.class"));
            }
          }
        });

    return test;
  }