|
| 1 | +/* |
| 2 | + * Copyright (C) 2016 The Android Open Source Project |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | + |
| 17 | +package com.google.cloud.tools.intellij.appengine.cloud; |
| 18 | + |
| 19 | +import com.intellij.execution.BeforeRunTask; |
| 20 | +import com.intellij.execution.RunManagerEx; |
| 21 | +import com.intellij.execution.configurations.RunConfiguration; |
| 22 | +import com.intellij.execution.impl.ConfigurationSettingsEditorWrapper; |
| 23 | +import com.intellij.ide.DataManager; |
| 24 | +import com.intellij.openapi.actionSystem.DataContext; |
| 25 | +import com.intellij.openapi.module.Module; |
| 26 | +import com.intellij.openapi.project.Project; |
| 27 | +import com.intellij.remoteServer.configuration.deployment.ModuleDeploymentSource; |
| 28 | +import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration; |
| 29 | +import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceType; |
| 30 | + |
| 31 | +import org.jetbrains.annotations.NotNull; |
| 32 | +import org.jetbrains.annotations.Nullable; |
| 33 | + |
| 34 | +import java.util.Collection; |
| 35 | +import java.util.List; |
| 36 | + |
| 37 | +import javax.swing.JComponent; |
| 38 | + |
| 39 | +/** |
| 40 | + * Base class for build-system (e.g. maven or gradle) deployment source types. Deployment |
| 41 | + * sources for specific build-systems should extend this providing the build-system specific |
| 42 | + * implementations. |
| 43 | + */ |
| 44 | +public abstract class BuildDeploymentSourceType extends ModuleDeploymentSourceType { |
| 45 | + |
| 46 | + /** |
| 47 | + * Creates a pre-deploy task ({@link BeforeRunTask}) for the given build-system and attaches it |
| 48 | + * to this module deployment source type. Invoked when a new deployment configuration is created. |
| 49 | + * |
| 50 | + * Provides the common functionality for creating the build-system packaging task, |
| 51 | + * delegating build-system specific functions to the concrete sub-types. |
| 52 | + * |
| 53 | + * Only creates a new task if one is not already configured. |
| 54 | + */ |
| 55 | + @Override |
| 56 | + public void setBuildBeforeRunTask( |
| 57 | + @NotNull RunConfiguration configuration, |
| 58 | + @NotNull ModuleDeploymentSource source) { |
| 59 | + |
| 60 | + Module module = source.getModule(); |
| 61 | + |
| 62 | + if (module == null) { |
| 63 | + return; |
| 64 | + } |
| 65 | + |
| 66 | + setConfiguration(configuration); |
| 67 | + |
| 68 | + RunManagerEx runManager = RunManagerEx.getInstanceEx(configuration.getProject()); |
| 69 | + final Collection<? extends BeforeRunTask> buildTasks = |
| 70 | + getBuildTasks(runManager, configuration); |
| 71 | + |
| 72 | + if (!hasBuildTaskForModule(buildTasks, module)) { |
| 73 | + BeforeRunTask buildTask = createBuildTask(module); |
| 74 | + if (buildTask != null) { |
| 75 | + List<BeforeRunTask> tasks = runManager.getBeforeRunTasks(configuration); |
| 76 | + tasks.add(buildTask); |
| 77 | + runManager.setBeforeRunTasks(configuration, tasks, true); |
| 78 | + } |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + /** |
| 83 | + * Updates the pre-deploy build tasks ({@link BeforeRunTask}) when the deployment source is |
| 84 | + * updated. |
| 85 | + * |
| 86 | + * Similar to {@link BuildDeploymentSourceType#setBuildBeforeRunTask( |
| 87 | + * RunConfiguration, ModuleDeploymentSource)}, but it is invoked when switching between |
| 88 | + * deployment sources in the UI. |
| 89 | + * |
| 90 | + * Only creates a new task if one is not already configured. In following the IntelliJ pattern |
| 91 | + * used for bundled deployment sources, this does NOT remove any existing tasks. |
| 92 | + */ |
| 93 | + @Override |
| 94 | + public void updateBuildBeforeRunOption( |
| 95 | + @NotNull JComponent runConfigurationEditorComponent, |
| 96 | + @NotNull Project project, |
| 97 | + @NotNull ModuleDeploymentSource source, |
| 98 | + boolean select) { |
| 99 | + |
| 100 | + final DataContext dataContext = |
| 101 | + DataManager.getInstance().getDataContext(runConfigurationEditorComponent); |
| 102 | + final ConfigurationSettingsEditorWrapper editor = |
| 103 | + ConfigurationSettingsEditorWrapper.CONFIGURATION_EDITOR_KEY.getData(dataContext); |
| 104 | + |
| 105 | + Module module = source.getModule(); |
| 106 | + |
| 107 | + if (module == null || editor == null) { |
| 108 | + return; |
| 109 | + } |
| 110 | + |
| 111 | + List<BeforeRunTask> buildTasks = editor.getStepsBeforeLaunch(); |
| 112 | + |
| 113 | + if (select && !hasBuildTaskForModule(buildTasks, module)) { |
| 114 | + BeforeRunTask buildTask = createBuildTask(module); |
| 115 | + if (buildTask != null) { |
| 116 | + editor.addBeforeLaunchStep(buildTask); |
| 117 | + } |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + /** |
| 122 | + * @return the collection of already configured {@link BeforeRunTask} subtypes for the given |
| 123 | + * build-system. |
| 124 | + */ |
| 125 | + @NotNull |
| 126 | + protected abstract Collection<? extends BeforeRunTask> getBuildTasks( |
| 127 | + RunManagerEx runManager, |
| 128 | + RunConfiguration configuration); |
| 129 | + |
| 130 | + /** |
| 131 | + * Creates a new instance of a {@link BeforeRunTask} for the corresponding build-system. |
| 132 | + * |
| 133 | + * This build task should encapsulate packaging of the build artifact for |
| 134 | + * the supplied module. |
| 135 | + * |
| 136 | + * @param module for which this task is scoped |
| 137 | + * @return a new build task |
| 138 | + */ |
| 139 | + |
| 140 | + @Nullable |
| 141 | + protected abstract BeforeRunTask createBuildTask(Module module); |
| 142 | + |
| 143 | + /** |
| 144 | + * Determines if there is already a configured build task in the supplied collection. |
| 145 | + * |
| 146 | + * Implementors should consider only those tasks corresponding to their build-systems, those |
| 147 | + * that produce the build artifact, and those scoped to the supplied module. |
| 148 | + * |
| 149 | + * @return boolean indicating if a build task exists. |
| 150 | + */ |
| 151 | + protected abstract boolean hasBuildTaskForModule( |
| 152 | + Collection<? extends BeforeRunTask> beforeRunTasks, Module module); |
| 153 | + |
| 154 | + /** |
| 155 | + * Manually set the deployment configuration so that its available immediately in the |
| 156 | + * deployment configuration dialog even if the user does not trigger any UI actions. This |
| 157 | + * prevents downstream npe's in {@link DeployToServerRunConfiguration#checkConfiguration()}. |
| 158 | + */ |
| 159 | + @SuppressWarnings("unchecked") |
| 160 | + private void setConfiguration(@NotNull RunConfiguration configuration) { |
| 161 | + if (configuration instanceof DeployToServerRunConfiguration) { |
| 162 | + DeployToServerRunConfiguration deployRunConfiguration = |
| 163 | + ((DeployToServerRunConfiguration) configuration); |
| 164 | + deployRunConfiguration.setDeploymentConfiguration(new AppEngineDeploymentConfiguration()); |
| 165 | + } |
| 166 | + } |
| 167 | + |
| 168 | +} |
0 commit comments