blob: 83bd4d8fb3b66edd288bc283db7acdbbf2538682 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.idea.gradle.run;
import com.android.tools.idea.gradle.invoker.GradleInvoker;
import com.android.tools.idea.gradle.invoker.GradleTaskExecutionListener;
import com.android.tools.idea.gradle.util.Projects;
import com.android.tools.idea.startup.AndroidStudioSpecificInitializer;
import com.intellij.compiler.options.CompileStepBeforeRun;
import com.intellij.execution.BeforeRunTaskProvider;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.util.concurrency.Semaphore;
import icons.AndroidIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Provides the "Gradle-aware Make" task for Run Configurations, which
* <ul>
* <li>is only available in Android Studio</li>
* <li>delegates to the regular "Make" if the project is not an Android Gradle project</li>
* <li>otherwise, invokes Gradle directly, to build the project</li>
* </ul>
*/
public class MakeBeforeRunTaskProvider extends BeforeRunTaskProvider<MakeBeforeRunTask> {
@NotNull public static final Key<MakeBeforeRunTask> ID = Key.create("Android.Gradle.BeforeRunTask");
private static final Logger LOG = Logger.getInstance(MakeBeforeRunTask.class);
private static final String TASK_NAME = "Gradle-aware Make";
@NotNull private final Project myProject;
public MakeBeforeRunTaskProvider(@NotNull Project project) {
myProject = project;
}
@Override
public Key<MakeBeforeRunTask> getId() {
return ID;
}
@Nullable
@Override
public Icon getIcon() {
return AndroidIcons.Android;
}
@Nullable
@Override
public Icon getTaskIcon(MakeBeforeRunTask task) {
return AndroidIcons.Android;
}
@Override
public String getName() {
return TASK_NAME;
}
@Override
public String getDescription(MakeBeforeRunTask task) {
return TASK_NAME;
}
@Override
public boolean isConfigurable() {
return false;
}
@Nullable
@Override
public MakeBeforeRunTask createTask(RunConfiguration runConfiguration) {
// "Gradle-aware Make" is only available in Android Studio.
return AndroidStudioSpecificInitializer.isAndroidStudio() ? new MakeBeforeRunTask() : null;
}
@Override
public boolean configureTask(RunConfiguration runConfiguration, MakeBeforeRunTask task) {
return false;
}
@Override
public boolean canExecuteTask(RunConfiguration configuration, MakeBeforeRunTask task) {
return true;
}
@Override
public boolean executeTask(final DataContext context,
final RunConfiguration configuration,
ExecutionEnvironment env,
MakeBeforeRunTask task) {
if (!Projects.isGradleProject(myProject) || !Projects.isExperimentalBuildEnabled(myProject)) {
CompileStepBeforeRun regularMake = new CompileStepBeforeRun(myProject);
return regularMake.executeTask(context, configuration, env, new CompileStepBeforeRun.MakeBeforeRunTask());
}
final AtomicBoolean result = new AtomicBoolean();
try {
final Semaphore done = new Semaphore();
done.down();
final GradleTaskExecutionListener listener = new GradleTaskExecutionListener() {
@Override
public void executionFinished(@NotNull List<String> tasks, int errorCount, int warningCount) {
result.set(errorCount == 0);
done.up();
}
};
if (myProject.isDisposed()) {
done.up();
}
else {
// To ensure that the "Run Configuration" waits for the Gradle tasks to be executed, we use SwingUtilities.invokeAndWait. I tried
// using Application.invokeAndWait but it never worked. IDEA also uses SwingUtilities in this scenario (see CompileStepBeforeRun.)
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
GradleInvoker gradleInvoker = GradleInvoker.getInstance(myProject);
gradleInvoker.make(context, listener, configuration);
}
});
done.waitFor();
}
}
catch (Throwable t) {
LOG.info("Unable to launch '" + TASK_NAME + "' task", t);
return false;
}
return result.get();
}
}