blob: aa48dd461fc758d58fcb814084239610af6d6c5b [file] [log] [blame]
/*
* Copyright (C) 2014 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.google.gct.idea.appengine.deploy;
import com.android.tools.idea.gradle.invoker.GradleInvoker;
import com.google.common.base.Strings;
import com.google.gct.idea.appengine.sdk.AppEngineSdk;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.CommandLineBuilder;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.ParametersList;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.process.*;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunnerLayoutUi;
import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.KeyValue;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.List;
/**
* Compiles and deploys a module to AppEngine using AppCfg.
*
* @author benwu
*/
class AppEngineUpdater {
private static final Logger LOG = Logger.getInstance("#com.google.gct.idea.appengine.deploy.AppEngineUpdater");
private final Project myProject;
private final Module myModule;
private final String myExplodedWarPath;
private final String mySdkPath;
private final String myClientSecret;
private final String myClientId;
private final String myRefreshToken;
private final String myVersion;
private final String myAppEngineProject;
AppEngineUpdater(Project project,
Module module,
String sdkPath,
String explodedWarPath,
String appEngineProject,
String version,
String clientSecret,
String clientId,
String refreshToken) {
myProject = project;
myModule = module;
mySdkPath = sdkPath;
myExplodedWarPath = explodedWarPath;
myClientSecret = clientSecret;
myClientId = clientId;
myRefreshToken = refreshToken;
myVersion = version;
myAppEngineProject = appEngineProject;
}
/**
* Starts the compile and upload async process.
*/
void startUploading() {
FileDocumentManager.getInstance().saveAllDocuments();
ProgressManager.getInstance().run(new Task.Backgroundable(myModule.getProject(), "Deploying application", true, null) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
compileAndUpload();
}
});
}
private void compileAndUpload() {
final Runnable startUploading = new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
startUploadingProcess();
}
});
}
};
GradleInvoker.getInstance(myProject).compileJava(new Module[]{myModule});
startUploading.run();
}
private void startUploadingProcess() {
final Process process;
final GeneralCommandLine commandLine;
try {
JavaParameters parameters = new JavaParameters();
parameters.configureByModule(myModule, JavaParameters.JDK_ONLY);
parameters.setMainClass("com.google.appengine.tools.admin.AppCfg");
AppEngineSdk mySdk = new AppEngineSdk(mySdkPath);
parameters.getClassPath().add(mySdk.getToolsApiJarFile().getAbsolutePath());
final List<KeyValue<String, String>> list = HttpConfigurable.getJvmPropertiesList(false, null);
if (!list.isEmpty()) {
final ParametersList parametersList = parameters.getVMParametersList();
for (KeyValue<String, String> value : list) {
parametersList.defineProperty(value.getKey(), value.getValue());
}
}
final ParametersList programParameters = parameters.getProgramParametersList();
programParameters.add("--application=" + myAppEngineProject);
if (!Strings.isNullOrEmpty(myVersion)) {
programParameters.add("--version=" + myVersion);
}
programParameters.add("--oauth2");
programParameters.add("--oauth2_client_secret=" + myClientSecret);
programParameters.add("--oauth2_client_id=" + myClientId);
programParameters.add("--oauth2_refresh_token=" + myRefreshToken);
programParameters.add("update");
programParameters.add(FileUtil.toSystemDependentName(myExplodedWarPath));
commandLine = CommandLineBuilder.createFromJavaParameters(parameters);
process = commandLine.createProcess();
}
catch (ExecutionException e) {
final String message = e.getMessage();
LOG.error("Cannot start uploading: " + message);
if (!EventQueue.isDispatchThread()) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Messages.showErrorDialog("Cannot start uploading: " + message, "Error");
}
});
}
else {
Messages.showErrorDialog("Cannot start uploading: " + message, "Error");
}
return;
}
final ProcessHandler processHandler = new FilteredOSProcessHandler(process, commandLine.getCommandLineString(),
new String[]{myRefreshToken, myClientSecret, myClientId});
final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
final ConsoleView console = TextConsoleBuilderFactory.getInstance().createBuilder(myModule.getProject()).getConsole();
final RunnerLayoutUi ui = RunnerLayoutUi.Factory.getInstance(myModule.getProject())
.create("Deploy", "Deploy to AppEngine", "Deploy Application", myModule.getProject());
final DefaultActionGroup group = new DefaultActionGroup();
ui.getOptions().setLeftToolbar(group, ActionPlaces.UNKNOWN);
ui.addContent(ui.createContent("upload", console.getComponent(), "Deploy Application", null, console.getPreferredFocusableComponent()));
console.attachToProcess(processHandler);
final RunContentDescriptor contentDescriptor =
new RunContentDescriptor(console, processHandler, ui.getComponent(), "Deploy to AppEngine");
group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_STOP_PROGRAM));
group.add(new CloseAction(executor, contentDescriptor, myModule.getProject()));
ExecutionManager.getInstance(myModule.getProject()).getContentManager().showRunContent(executor, contentDescriptor);
processHandler.startNotify();
}
private class FilteredOSProcessHandler extends OSProcessHandler {
String[] tokensToFilter;
FilteredOSProcessHandler(@NotNull final Process process, @Nullable final String commandLine, String[] filteredTokens) {
super(process, commandLine);
tokensToFilter = filteredTokens;
}
@Override
public void notifyTextAvailable(final String text, final Key outputType) {
String newText = text;
if (tokensToFilter != null) {
for (String token : tokensToFilter) {
newText = newText.replace(token, "*****");
}
}
super.notifyTextAvailable(newText, outputType);
}
}
}