1 /* 2 * Copyright (C) 2019 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 package com.android.atest.run; 17 18 import com.android.atest.AtestUtils; 19 import com.android.atest.Constants; 20 import com.android.atest.commandAdapter.CommandRunner; 21 import com.android.atest.dialog.MessageDialog; 22 import com.android.atest.toolWindow.AtestToolWindow; 23 import com.android.atest.widget.AtestNotification; 24 import com.google.common.base.Strings; 25 import com.intellij.execution.ExecutionException; 26 import com.intellij.execution.Executor; 27 import com.intellij.execution.configurations.*; 28 import com.intellij.execution.runners.ExecutionEnvironment; 29 import com.intellij.notification.Notifications; 30 import com.intellij.openapi.diagnostic.Logger; 31 import com.intellij.openapi.options.SettingsEditor; 32 import com.intellij.openapi.project.Project; 33 import com.intellij.openapi.util.InvalidDataException; 34 import com.intellij.openapi.util.text.StringUtil; 35 import com.intellij.openapi.wm.ToolWindow; 36 import com.intellij.openapi.wm.ToolWindowManager; 37 import org.jdom.Element; 38 import org.jetbrains.annotations.NotNull; 39 import org.jetbrains.annotations.Nullable; 40 41 /** Runs configurations which can be managed by a user and displayed in the UI. */ 42 public class AtestRunConfiguration extends LocatableConfigurationBase { 43 44 private static final Logger LOG = Logger.getInstance(AtestRunConfiguration.class); 45 public static final String TEST_TARGET_KEY = "testTarget"; 46 public static final String LUNCH_TARGET_KEY = "lunchTarget"; 47 private String mTestTarget = ""; 48 private String mLunchTarget = ""; 49 AtestRunConfiguration(Project project, ConfigurationFactory factory, String name)50 protected AtestRunConfiguration(Project project, ConfigurationFactory factory, String name) { 51 super(project, factory, name); 52 } 53 54 /** 55 * Reads the run configuration settings from the file system. 56 * 57 * @param element an Element object to read. 58 * @throws InvalidDataException if the data is invalid. 59 */ 60 @Override readExternal(@otNull Element element)61 public void readExternal(@NotNull Element element) throws InvalidDataException { 62 Element child = element.getChild(TEST_TARGET_KEY); 63 if (hasValue(child)) { 64 mTestTarget = child.getTextTrim(); 65 } 66 child = element.getChild(LUNCH_TARGET_KEY); 67 if (hasValue(child)) { 68 mLunchTarget = child.getTextTrim(); 69 } 70 } 71 72 /** 73 * Checks the element has value or not. 74 * 75 * @param element an Element object to check. 76 * @return true if the element has value. 77 */ hasValue(Element element)78 private boolean hasValue(Element element) { 79 return element != null && !Strings.isNullOrEmpty(element.getTextTrim()); 80 } 81 82 /** 83 * Stores the run configuration settings at file system. 84 * 85 * @param element an Element object to write. 86 */ 87 @Override writeExternal(@otNull Element element)88 public void writeExternal(@NotNull Element element) { 89 setElementChild(element, TEST_TARGET_KEY, mTestTarget); 90 setElementChild(element, LUNCH_TARGET_KEY, mLunchTarget); 91 super.writeExternal(element); 92 } 93 94 /** 95 * Sets the child element for an element. 96 * 97 * @param element an Element object to set. 98 * @param key the key of the child Element object. 99 * @param value the value of the child Element object. 100 */ setElementChild(@otNull Element element, String key, String value)101 private void setElementChild(@NotNull Element element, String key, String value) { 102 Element child = new Element(key); 103 child.setText(value); 104 element.addContent(child); 105 } 106 107 /** 108 * Returns the UI control for editing the run configuration settings. If additional control over 109 * validation is required, the object returned from this method may also implement {@link 110 * com.intellij.execution.impl.CheckableRunConfigurationEditor}. The returned object can also 111 * implement {@link com.intellij.openapi.options.SettingsEditorGroup} if the settings it 112 * provides need to be displayed in multiple tabs. 113 * 114 * @return Atest settings editor component. 115 */ 116 @NotNull 117 @Override getConfigurationEditor()118 public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() { 119 return new AtestSettingsEditor(); 120 } 121 122 /** 123 * Checks whether the run configuration settings are valid. Note that this check may be invoked 124 * on every change (i.e. after each character typed in an input field). 125 * 126 * @throws RuntimeConfigurationException if the configuration settings contain a non-fatal 127 * problem which the user should be warned about but the execution should still be allowed. 128 */ 129 @Override checkConfiguration()130 public void checkConfiguration() throws RuntimeConfigurationException { 131 if (StringUtil.isEmptyOrSpaces(mTestTarget)) { 132 throw new RuntimeConfigurationWarning("Test target not defined"); 133 } 134 if (StringUtil.isEmptyOrSpaces(mLunchTarget)) { 135 throw new RuntimeConfigurationWarning("Lunch target not defined"); 136 } 137 } 138 139 /** 140 * Prepares for executing a specific instance of the run configuration. 141 * 142 * <p>Since Atest plugin uses tool window to output the message. It always returns null to 143 * handle the process inside Atest plugin. 144 * 145 * @param executor the execution mode selected by the user (run, debug, profile etc.) 146 * @param executionEnvironment the environment object containing additional settings for 147 * executing the configuration. 148 * @throws ExecutionException if exception happens when executing. 149 * @return the RunProfileState describing the process which is about to be started, or null if 150 * it won't start the process. 151 */ 152 @Nullable 153 @Override getState( @otNull Executor executor, @NotNull ExecutionEnvironment executionEnvironment)154 public RunProfileState getState( 155 @NotNull Executor executor, @NotNull ExecutionEnvironment executionEnvironment) 156 throws ExecutionException { 157 AtestToolWindow atestToolWindow = 158 AtestToolWindow.getInstance(executionEnvironment.getProject()); 159 160 if (!showAtestTW(executionEnvironment.getProject())) { 161 return null; 162 } 163 String workPath = 164 AtestUtils.getAndroidRoot(executionEnvironment.getProject().getBasePath()); 165 atestToolWindow.setLunchTarget(mLunchTarget); 166 atestToolWindow.setTestTarget(mTestTarget); 167 try { 168 CommandRunner runner = 169 new CommandRunner( 170 mLunchTarget, 171 mTestTarget, 172 workPath, 173 atestToolWindow, 174 executionEnvironment.getProject()); 175 runner.run(); 176 } catch (IllegalArgumentException exception) { 177 String errorMessage = AtestUtils.checkError(mLunchTarget, mTestTarget, workPath); 178 MessageDialog.showMessageDialog(errorMessage); 179 } 180 return null; 181 } 182 183 /** 184 * Shows the Atest tool window. 185 * 186 * @param project the project in which the run configuration will be used. 187 * @return true if show Atest tool window successful. 188 */ showAtestTW(@otNull Project project)189 private boolean showAtestTW(@NotNull Project project) { 190 boolean result = false; 191 ToolWindow atestTWController = 192 ToolWindowManager.getInstance(project).getToolWindow(Constants.ATEST_TOOL_WINDOW); 193 if (atestTWController != null) { 194 atestTWController.show(null); 195 result = true; 196 } else { 197 Notifications.Bus.notify(new AtestNotification(Constants.ATEST_WINDOW_FAIL)); 198 LOG.error("Can't get Atest tool window."); 199 } 200 return result; 201 } 202 getTestTarget()203 public String getTestTarget() { 204 return mTestTarget; 205 } 206 setTestTarget(@otNull String testTarget)207 public void setTestTarget(@NotNull String testTarget) { 208 mTestTarget = testTarget; 209 } 210 getLaunchTarget()211 public String getLaunchTarget() { 212 return mLunchTarget; 213 } 214 setLaunchTarget(@otNull String launchTarget)215 public void setLaunchTarget(@NotNull String launchTarget) { 216 mLunchTarget = launchTarget; 217 } 218 } 219